Hardening Guide ¶
+Overview ¶
+There are several ways to do hardening and securing of nginx. In this documentation two guides are used, the guides are +overlapping in some points:
+-
+
- nginx CIS Benchmark +
- cipherlist.eu (one of many forks of the now dead project cipherli.st) +
This guide describes, what of the different configurations described in those guides is already implemented as default +in the nginx implementation of kubernetes ingress, what needs to be configured, what is obsolete due to the fact that +the nginx is running as container (the CIS benchmark relates to a non-containerized installation) and what is difficult +or not possible.
+Be aware that this is only a guide and you are responsible for your own implementation. Some of the configurations may +lead to have specific clients unable to reach your site or similar consequences.
+This guide refers to chapters in the CIS Benchmark. For full explanation you should refer to the benchmark document itself
+Configuration Guide ¶
+Chapter in CIS benchmark | +Status | +Default | +Action to do if not default | +
---|---|---|---|
1 Initial Setup | ++ | + | + |
+ | + | + | + |
1.1 Installation | ++ | + | + |
1.1.1 Ensure NGINX is installed (Scored) | +OK | +done through helm charts / following documentation to deploy nginx ingress | ++ |
1.1.2 Ensure NGINX is installed from source (Not Scored) | +OK | +done through helm charts / following documentation to deploy nginx ingress | ++ |
+ | + | + | + |
1.2 Configure Software Updates | ++ | + | + |
1.2.1 Ensure package manager repositories are properly configured (Not Scored) | +OK | +done via helm, nginx version could be overwritten, however compability is not ensured then | ++ |
1.2.2 Ensure the latest software package is installed (Not Scored) | +ACTION NEEDED | +done via helm, nginx version could be overwritten, however compability is not ensured then | +Plan for periodic updates | +
+ | + | + | + |
2 Basic Configuration | ++ | + | + |
+ | + | + | + |
2.1 Minimize NGINX Modules | ++ | + | + |
2.1.1 Ensure only required modules are installed (Not Scored) | +OK | +Already only needed modules are installed, however proposals for further reduction are welcome | ++ |
2.1.2 Ensure HTTP WebDAV module is not installed (Scored) | +RISK TO BE ACCEPTED | +It is installed, see compile options here. Disabling that would require building own image for nginx ingress controller. The effort is too high in comparison to the achieved effect | ++ |
2.1.3 Ensure modules with gzip functionality are disabled (Scored) | +RISK TO BE ACCEPTED | +See previous answer | ++ |
2.1.4 Ensure the autoindex module is disabled (Scored) | +OK | +No autoindex configs so far in ingress defaults | ++ |
+ | + | + | + |
2.2 Account Security | ++ | + | + |
2.2.1 Ensure that NGINX is run using a non-privileged, dedicated service account (Not Scored) | +OK | +Pod configured as user www-data: See this line in helm chart values. Compiled with user www-data: See this line in build script | ++ |
2.2.2 Ensure the NGINX service account is locked (Scored) | +OK | +Docker design ensures this | ++ |
2.2.3 Ensure the NGINX service account has an invalid shell (Scored) | +OK | +Shell is nologin: see this line in build script | ++ |
+ | + | + | + |
2.3 Permissions and Ownership | ++ | + | + |
2.3.1 Ensure NGINX directories and files are owned by root (Scored) | +OK | +Obsolete through docker-design and ingress controller needs to update the configs dynamically | ++ |
2.3.2 Ensure access to NGINX directories and files is restricted (Scored) | +OK | +See previous answer | ++ |
2.3.3 Ensure the NGINX process ID (PID) file is secured (Scored) | +OK | +No PID-File due to docker design | ++ |
2.3.4 Ensure the core dump directory is secured (Not Scored) | +OK | +No working_directory configured by default | ++ |
+ | + | + | + |
2.4 Network Configuration | ++ | + | + |
2.4.1 Ensure NGINX only listens for network connections on authorized ports (Not Scored) | +OK | +Ensured by automatic nginx.conf configuration | ++ |
2.4.2 Ensure requests for unknown host names are rejected (Not Scored) | +OK | +They are not rejected but send to the "default backend" delivering approriate errors (mostly 404) | ++ |
2.4.3 Ensure keepalive_timeout is 10 seconds or less, but not 0 (Scored) | +ACTION NEEDED | +Default is 75s | +configure keep-alive to 10 seconds according to this documentation | +
2.4.4 Ensure send_timeout is set to 10 seconds or less, but not 0 (Scored) | +RISK TO BE ACCEPTED | +Not configured, however the nginx default is 60s | +Not configurable | +
+ | + | + | + |
2.5 Information Disclosure | ++ | + | + |
2.5.1 Ensure server_tokens directive is set to off (Scored) |
+OK | +server_tokens is configured to off by defaukt | ++ |
2.5.2 Ensure default error and index.html pages do not reference NGINX (Scored) | +ACTION NEEDED | +404 shows no version at all, 503 and 403 show "nginx", which is hardcoded see this line in nginx source code | +configure custom error pages at least for 403, 404 and 503 and 500 | +
2.5.3 Ensure hidden file serving is disabled (Not Scored) | +ACTION NEEDED | +config not set | +configure a config.server-snippet Snippet, but beware of .well-known challenges or similar. Refer to the benchmark here please | +
2.5.4 Ensure the NGINX reverse proxy does not enable information disclosure (Scored) | +ACTION NEEDED | +hide not configured | +configure hide-headers with array of "X-Powered-By" and "Server": according to this documentation | +
+ | + | + | + |
3 Logging | ++ | + | + |
+ | + | + | + |
3.1 Ensure detailed logging is enabled (Not Scored) | +OK | +Ningx ingress has a very detailled log format by default | ++ |
3.2 Ensure access logging is enabled (Scored) | +OK | +Access log is enabled by default | ++ |
3.3 Ensure error logging is enabled and set to the info logging level (Scored) | +OK | +Error log is configured by default. The log level does not matter, because it is all sent to STDOUT anyway | ++ |
3.4 Ensure log files are rotated (Scored) | +OBSOLETE | +Log file handling is not part of the nginx ingress and should be handled separatly | ++ |
3.5 Ensure error logs are sent to a remote syslog server (Not Scored) | +OBSOLETE | +See previous answer | ++ |
3.6 Ensure access logs are sent to a remote syslog server (Not Scored) | +OBSOLETE | +See previous answer | ++ |
3.7 Ensure proxies pass source IP information (Scored) | +OK | +Headers are set by default | ++ |
+ | + | + | + |
4 Encryption | ++ | + | + |
+ | + | + | + |
4.1 TLS / SSL Configuration | ++ | + | + |
4.1.1 Ensure HTTP is redirected to HTTPS (Scored) | +OK | +Redirect to TLS is default | ++ |
4.1.2 Ensure a trusted certificate and trust chain is installed (Not Scored) | +ACTION NEEDED | +For installing certs there are enough manuals in the web. A good way is to use lets encrypt through cert-manager | +Install proper certificates or use lets encrypt with cert-manager | +
4.1.3 Ensure private key permissions are restricted (Scored) | +ACTION NEEDED | +See previous answer | ++ |
4.1.4 Ensure only modern TLS protocols are used (Scored) | +OK/ACTION NEEDED | +Default is TLS 1.2 + 1.3, while this is okay for CIS Benchmark, cipherlist.eu only recommends 1.3. This may cut off old OS's | +Set controller.config.ssl-protocols to "TLSv1.3" | +
4.1.5 Disable weak ciphers (Scored) | +ACTION NEEDED | +Default ciphers are already good, but cipherlist.eu recommends even stronger ciphers | +Set controller.config.ssl-ciphers to "EECDH+AESGCM:EDH+AESGCM" | +
4.1.6 Ensure custom Diffie-Hellman parameters are used (Scored) | +ACTION NEEDED | +No custom DH parameters are generated | +Generate dh parameters for each ingress deployment you use - see here for a how to | +
4.1.7 Ensure Online Certificate Status Protocol (OCSP) stapling is enabled (Scored) | +ACTION NEEDED | +Not enabled | +set via this configuration parameter | +
4.1.8 Ensure HTTP Strict Transport Security (HSTS) is enabled (Scored) | +OK | +HSTS is enabled by default | ++ |
4.1.9 Ensure HTTP Public Key Pinning is enabled (Not Scored) | +ACTION NEEDED / RISK TO BE ACCEPTED | +HKPK not enabled by default | +If lets encrypt is not used, set correct HPKP header. There are several ways to implement this - with the helm charts it works via controller.add-headers. If lets encrypt is used, this is complicated, a solution here is yet unknown | +
4.1.10 Ensure upstream server traffic is authenticated with a client certificate (Scored) | +DEPENDS ON BACKEND | +Highly dependend on backends, not every backend allows configuring this, can also be mitigated via a service mesh | +If backend allows it, manual is here | +
4.1.11 Ensure the upstream traffic server certificate is trusted (Not Scored) | +DEPENDS ON BACKEND | +Highly dependend on backends, not every backend allows configuring this, can also be mitigated via a service mesh | +If backend allows it, see configuration here | +
4.1.12 Ensure your domain is preloaded (Not Scored) | +ACTION NEEDED | +Preload is not active by default | +Set controller.config.hsts-preload to true | +
4.1.13 Ensure session resumption is disabled to enable perfect forward security (Scored) | +ACTION NEEDED | +Session tickets are enabled by default | +Set controller.config.ssl-session-tickets to false | +
4.1.14 Ensure HTTP/2.0 is used (Not Scored) | +OK | +http2 is set by default | ++ |
+ | + | + | + |
5 Request Filtering and Restrictions | ++ | + | + |
+ | + | + | + |
5.1 Access Control | ++ | + | + |
5.1.1 Ensure allow and deny filters limit access to specific IP addresses (Not Scored) | +OK/ACTION NEEDED | +Depends on use case, geo ip module is compiled into nginx ingress controller, there are several ways to use it | +If needed set IP restrictions via annotations or work with config snippets (be careful with lets-encrypt-http-challenge!) | +
5.1.2 Ensure only whitelisted HTTP methods are allowed (Not Scored) | +OK/ACTION NEEDED | +Depends on use case | +If required it can be set via config snippet | +
+ | + | + | + |
5.2 Request Limits | ++ | + | + |
5.2.1 Ensure timeout values for reading the client header and body are set correctly (Scored) | +ACTION NEEDED | +Default timeout is 60s | +Set via this configuration parameter and respective body aequivalent | +
5.2.2 Ensure the maximum request body size is set correctly (Scored) | +ACTION NEEDED | +Default is 1m | +set via this configuration parameter | +
5.2.3 Ensure the maximum buffer size for URIs is defined (Scored) | +ACTION NEEDED | +Default is 4 8k | +Set via this configuration parameter | +
5.2.4 Ensure the number of connections per IP address is limited (Not Scored) | +OK/ACTION NEEDED | +No limit set | +Depends on use case, limit can be set via these annotations | +
5.2.5 Ensure rate limits by IP address are set (Not Scored) | +OK/ACTION NEEDED | +No limit set | +Depends on use case, limit can be set via these annotations | +
+ | + | + | + |
5.3 Browser Security | ++ | + | + |
5.3.1 Ensure X-Frame-Options header is configured and enabled (Scored) | +ACTION NEEDED | +Header not set by default | +Several ways to implement this - with the helm charts it works via controller.add-headers | +
5.3.2 Ensure X-Content-Type-Options header is configured and enabled (Scored) | +ACTION NEEDED | +See previous answer | +See previous answer | +
5.3.3 Ensure the X-XSS-Protection Header is enabled and configured properly (Scored) | +ACTION NEEDED | +See previous answer | +See previous answer | +
5.3.4 Ensure that Content Security Policy (CSP) is enabled and configured properly (Not Scored) | +ACTION NEEDED | +See previous answer | +See previous answer | +
5.3.5 Ensure the Referrer Policy is enabled and configured properly (Not Scored) | +ACTION NEEDED | +Depends on application. It should be handled in the applications webserver itself, not in the load balancing ingress | +check backend webserver | +
+ | + | + | + |
6 Mandatory Access Control | +n/a | +too high level, depends on backends | ++ |