|
80 | 80 | end
|
81 | 81 |
|
82 | 82 | # determine all required paths
|
83 |
| -nginx_path = '/etc/nginx' |
84 |
| -nginx_conf = File.join(nginx_path, 'nginx.conf') |
85 |
| -nginx_confd = File.join(nginx_path, 'conf.d') |
86 |
| -nginx_enabled = File.join(nginx_path, 'sites-enabled') |
87 |
| -nginx_hardening = File.join(nginx_confd, '90.hardening.conf') |
88 |
| -conf_paths = [nginx_conf, nginx_hardening] |
| 83 | +nginx_path = '/etc/nginx' |
| 84 | +nginx_conf = File.join(nginx_path, 'nginx.conf') |
| 85 | +nginx_confd = File.join(nginx_path, 'conf.d') |
| 86 | +nginx_enabled = File.join(nginx_path, 'sites-enabled') |
| 87 | +nginx_hardening = File.join(nginx_confd, '90.hardening.conf') |
| 88 | +conf_paths = [nginx_conf, nginx_hardening] |
| 89 | +nginx_parsed_config = command('nginx -T').stdout |
89 | 90 |
|
90 | 91 | options = {
|
91 | 92 | assignment_regex: /^\s*([^:]*?)\s*\ \s*(.*?)\s*;$/
|
|
157 | 158 | impact 1.0
|
158 | 159 | title 'Disable server_tokens directive'
|
159 | 160 | desc 'Disables emitting nginx version in error messages and in the “Server” response header field.'
|
160 |
| - describe parse_config_file(nginx_conf, options) do |
| 161 | + describe parse_config(nginx_parsed_config, options) do |
161 | 162 | its('server_tokens') { should eq 'off' }
|
162 | 163 | end
|
163 | 164 | end
|
|
166 | 167 | impact 1.0
|
167 | 168 | title 'Prevent buffer overflow attacks'
|
168 | 169 | desc 'Buffer overflow attacks are made possible by writing data to a buffer and exceeding that buffer boundary and overwriting memory fragments of a process. To prevent this in nginx we can set buffer size limitations for all clients.'
|
169 |
| - describe parse_config_file(nginx_conf, options) do |
| 170 | + describe parse_config(nginx_parsed_config, options) do |
170 | 171 | its('client_body_buffer_size') { should eq CLIENT_BODY_BUFFER_SIZE }
|
171 | 172 | end
|
172 |
| - describe parse_config_file(nginx_conf, options) do |
| 173 | + describe parse_config(nginx_parsed_config, options) do |
173 | 174 | its('client_max_body_size') { should eq CLIENT_MAX_BODY_SIZE }
|
174 | 175 | end
|
175 |
| - describe parse_config_file(nginx_hardening, options) do |
| 176 | + describe parse_config(nginx_parsed_config, options) do |
176 | 177 | its('client_header_buffer_size') { should eq CLIENT_HEADER_BUFFER_SIZE }
|
177 | 178 | end
|
178 |
| - describe parse_config_file(nginx_hardening, options) do |
| 179 | + describe parse_config(nginx_parsed_config, options) do |
179 | 180 | its('large_client_header_buffers') { should eq LARGE_CLIENT_HEADER_BUFFER }
|
180 | 181 | end
|
181 | 182 | end
|
|
184 | 185 | impact 1.0
|
185 | 186 | title 'Control simultaneous connections'
|
186 | 187 | desc 'NginxHttpLimitZone module to limit the number of simultaneous connections for the assigned session or as a special case, from one IP address.'
|
187 |
| - describe parse_config_file(nginx_hardening, options) do |
| 188 | + describe parse_config(nginx_parsed_config, options) do |
188 | 189 | its('limit_conn_zone') { should eq '$binary_remote_addr zone=default:10m' }
|
189 | 190 | end
|
190 |
| - describe parse_config_file(nginx_hardening, options) do |
| 191 | + describe parse_config(nginx_parsed_config, options) do |
191 | 192 | its('limit_conn') { should eq 'default 5' }
|
192 | 193 | end
|
193 | 194 | end
|
|
196 | 197 | impact 1.0
|
197 | 198 | title 'Prevent clickjacking'
|
198 | 199 | desc 'Do not allow the browser to render the page inside an frame or iframe.'
|
199 |
| - describe parse_config_file(nginx_hardening, options_add_header) do |
| 200 | + describe parse_config(nginx_parsed_config, options_add_header) do |
200 | 201 | its('add_header') { should include 'X-Frame-Options SAMEORIGIN' }
|
201 | 202 | end
|
202 | 203 | end
|
|
205 | 206 | impact 1.0
|
206 | 207 | title 'Enable Cross-site scripting filter'
|
207 | 208 | desc 'This header is used to configure the built in reflective XSS protection. This tells the browser to block the response if it detects an attack rather than sanitising the script.'
|
208 |
| - describe parse_config_file(nginx_hardening, options_add_header) do |
| 209 | + describe parse_config(nginx_parsed_config, options_add_header) do |
209 | 210 | its('add_header') { should include 'X-XSS-Protection "1; mode=block"' }
|
210 | 211 | end
|
211 | 212 | end
|
|
214 | 215 | impact 1.0
|
215 | 216 | title 'Disable content-type sniffing'
|
216 | 217 | desc 'It prevents browser from trying to mime-sniff the content-type of a response away from the one being declared by the server. It reduces exposure to drive-by downloads and the risks of user uploaded content that, with clever naming, could be treated as a different content-type, like an executable.'
|
217 |
| - describe parse_config_file(nginx_hardening, options_add_header) do |
| 218 | + describe parse_config(nginx_parsed_config, options_add_header) do |
218 | 219 | its('add_header') { should include 'X-Content-Type-Options nosniff' }
|
219 | 220 | end
|
220 | 221 | end
|
|
224 | 225 | title 'TLS Protocols'
|
225 | 226 | desc 'When choosing a cipher during an SSLv3 or TLSv1 handshake, normally the client\'s preference is used. If this directive is enabled, the server\'s preference will be used instead.'
|
226 | 227 | ref 'SSL Hardening config', url: 'https://mozilla.github.io/server-side-tls/ssl-config-generator/'
|
227 |
| - describe file(nginx_hardening) do |
228 |
| - its('content') { should match(/^\s*ssl_protocols TLSv1.2;$/) } |
229 |
| - its('content') { should match(/^\s*ssl_session_tickets off;$/) } |
230 |
| - its('content') { should match(/^\s*ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';$/) } |
231 |
| - its('content') { should match(/^\s*ssl_prefer_server_ciphers on;$/) } |
232 |
| - its('content') { should match(%r{^\s*ssl_dhparam /etc/nginx/dh2048.pem;$}) } |
233 |
| - # its('content') { should match(/^\s*ssl on;$/) } |
| 228 | + describe parse_config(nginx_parsed_config, options) do |
| 229 | + its('ssl_protocols') { should eq 'TLSv1.2' } |
| 230 | + its('ssl_session_tickets') { should eq 'off' } |
| 231 | + its('ssl_ciphers') { should eq '\'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256\'' } |
| 232 | + its('ssl_prefer_server_ciphers') { should eq 'on' } |
| 233 | + its('ssl_dhparam') { should eq '/etc/nginx/dh2048.pem' } |
234 | 234 | end
|
235 | 235 | end
|
236 | 236 |
|
237 | 237 | control 'nginx-13' do
|
238 | 238 | impact 1.0
|
239 | 239 | title 'Add HSTS Header'
|
240 | 240 | desc 'HTTP Strict Transport Security (HSTS) is a web security policy mechanism which helps to protect websites against protocol downgrade attacks and cookie hijacking. It allows web servers to declare that web browsers (or other complying user agents) should only interact with it using secure HTTPS connections, and never via the insecure HTTP protocol. HSTS is an IETF standards track protocol and is specified in RFC 6797.'
|
241 |
| - describe file(nginx_hardening) do |
242 |
| - its('content') { should match(/^\s*add_header Strict-Transport-Security max-age=15768000;$/) } |
| 241 | + describe parse_config(nginx_parsed_config, options_add_header) do |
| 242 | + its('add_header') { should include 'Strict-Transport-Security max-age=15768000' } |
243 | 243 | end
|
244 | 244 | end
|
245 | 245 |
|
|
258 | 258 | impact 1.0
|
259 | 259 | title 'Content-Security-Policy'
|
260 | 260 | desc 'The Content-Security-Policy HTTP response header helps you reduce XSS risks on modern browsers by declaring what dynamic resources are allowed to load via a HTTP Header'
|
261 |
| - describe parse_config_file(nginx_hardening, options_add_header) do |
262 |
| - its('content') { should match(/^\s*add_header Content-Security-Policy "script-src 'self'; object-src 'self'";$/) } |
| 261 | + describe parse_config(nginx_parsed_config, options_add_header) do |
| 262 | + its('add_header') { should include 'Content-Security-Policy "script-src \'self\'; object-src \'self\'"' } |
263 | 263 | end
|
264 | 264 | end
|
265 | 265 |
|
266 | 266 | control 'nginx-16' do
|
267 | 267 | impact 1.0
|
268 | 268 | title 'Set cookie with HttpOnly and Secure flag'
|
269 | 269 | desc 'You can mitigate most of the common Cross Site Scripting attack using HttpOnly and Secure flag in a cookie. Without having HttpOnly and Secure, it is possible to steal or manipulate web application session and cookies and it’s dangerous.'
|
270 |
| - describe parse_config_file(nginx_hardening, options_add_header) do |
271 |
| - its('content') { should match(/^\s*set_cookie_flag * HttpOnly secure;$/) } |
| 270 | + describe parse_config(nginx_parsed_config, options_add_header) do |
| 271 | + its('set_cookie_flag') { should include '* HttpOnly secure' } |
272 | 272 | end
|
273 | 273 | end
|
274 | 274 |
|
275 | 275 | control 'nginx-17' do
|
276 | 276 | impact 1.0
|
277 | 277 | title 'Control timeouts to improve performance'
|
278 | 278 | desc 'Control timeouts to improve server performance and cut clients.'
|
279 |
| - describe parse_config_file(nginx_conf, options) do |
| 279 | + describe parse_config(nginx_parsed_config, options) do |
280 | 280 | its('keepalive_timeout') { should eq KEEPALIVE_TIMEOUT }
|
281 | 281 | end
|
282 |
| - describe parse_config_file(nginx_hardening, options) do |
| 282 | + describe parse_config(nginx_parsed_config, options) do |
283 | 283 | its('client_body_timeout') { should eq CLIENT_BODY_TIMEOUT }
|
284 | 284 | end
|
285 |
| - describe parse_config_file(nginx_hardening, options) do |
| 285 | + describe parse_config(nginx_parsed_config, options) do |
286 | 286 | its('client_header_timeout') { should eq CLIENT_HEADER_TIMEOUT }
|
287 | 287 | end
|
288 |
| - describe parse_config_file(nginx_hardening, options) do |
| 288 | + describe parse_config(nginx_parsed_config, options) do |
289 | 289 | its('send_timeout') { should eq SEND_TIMEOUT }
|
290 | 290 | end
|
291 | 291 | end
|
0 commit comments