Securing your NGINX or APACHE web server requires careful consideration of many factors. A good place to begin is by checking your HTTP security headers to see if you are following industry best practices.
A minor change to the web server configuration is often all that’s needed. An additional layer of protection is provided by HTTP security headers, which help to reduce the risk of attacks and security vulnerabilities. For the purpose of this post, we’ll take a closer look at a few of them to show you how to put them into action.
What are HTTP security headers?
Content and HTTP response headers are sent back to the browser whenever a web server responds to a browser request for a page. Headers like Content-Encoding, Cache-Control and Status Codes contain meta data.
HTTP security headers are also included, which tell your browser how to handle your website’s content. Strict-Transport-Security, for example, forces the browser to use HTTPS exclusively. Here, in no particular order, are examples of HTTP security headers that you should know about and consider implementing.
The X-XSS-Protection header is designed to enable modern web browsers’ built-in cross-site scripting (XSS) filtering. Usually this is enabled by default. Internet Explorer 8+, Chrome, and Safari all support X-XSS-Protection. The following is an example of how the header looks like: X-XSS-Protection: 1; mode=block
Enable X-XSS-Protection in NGINX
add_header X-XSS-Protection “1; mode=block” always;
Enable X-XSS-Protection in Apache
header always set X-XSS-Protection “1; mode=block”
2. Content Security Policy
Content security policies are currently supported by all major browsers. This won’t cause any issues if the content is delivered to an older browser; it will just be ignored.
Content-Security-Policy has a wide range of directives that can be used. Scripts from both the current domain (defined by ‘self’) and alexbobes.com are allowed in this example: Content-Security-Policy: script-src ‘self’ https://alexbobes.com
OWASP provides the following list of CSP directives, along with a brief description of each:
default-srcDefine loading policy for all resources type in case of a resource type dedicated directive is not defined (fallback),
script-srcDefine which scripts the protected resource can execute,
object-srcDefine from where the protected resource can load plugins,
style-srcDefine which styles (CSS) the user applies to the protected resource,
img-srcDefine from where the protected resource can load images,
media-srcDefine from where the protected resource can load video and audio,
frame-srcDefine from where the protected resource can embed frames,
frame-ancestorsSpecifies valid parents that may embed a page using
font-srcDefine from where the protected resource can load fonts,
connect-srcDefine which URIs the protected resource can load using script interfaces,
form-actionDefine which URIs can be used as the action of HTML form elements,
sandboxSpecifies an HTML sandbox policy that the user agent applies to the protected resource,
script-nonceDefine script execution by requiring the presence of the specified nonce on script elements,
plugin-typesDefine the set of plugins that can be invoked by the protected resource by limiting the types of resources that can be embedded,
reflected-xssInstructs a user agent to activate or deactivate any heuristics used to filter or block reflected cross-site scripting attacks, equivalent to the effects of the non-standard
report-uriSpecifies a URI to which the user agent sends reports about policy violation
The X-Frame-Options header prevents iframes from loading on your website, preventing clickjacking. Browsers that support it include Internet Explorer 8, Google Chrome 4, Mozilla Firefox 3, Apple Safari 4, and Opera 10.5. The following is an example of a X-Frame-Options header: X-Frame-Options: SAMEORIGIN
Enable X-Frame-Options in NGINX
add_header X-Frame-Options “SAMEORIGIN” always;
Enable X-Frame-Options in Apache
header always set X-Frame-Options “SAMEORIGIN”
4. HTTP Strict Transport Security
For extra security, web browsers can only communicate with web servers over HTTPS. This ensures that the connection cannot be established via an insecure HTTP connection that could be vulnerable to attacks.
All modern browsers except Opera Mini and older versions of Internet Explorer support HTTP strict transport security.
Enabling HTTP Strict Transport Security on your origin server is a prerequisite before you can proceed with setting it up. The web server will start adding an additional response header to tell the browser to only communicate over HTTPS once it is enabled on the server side. The response header will look something similar to: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload.
- max-age: it specifies the maximum number of seconds for which the web server should only deliver via HTTPS.
- includeSubDomains: not mandatory; all of the site’s subdomains will also be protected by HSTS as a result of defining this directive
preload: not mandatory; it is possible for the site owner to add their website to Chrome’s “preload list,” which is a list of HTTPS-only sites that have been hardcoded into the browser
Any subsequent visits to http://domain.com will be redirected to https://domain.com if the HTTP Strict Transport Security header is present on the website you are visiting. As long as the expiration time has not expired, the browser will continue to do so. However, the expiration time is updated and refreshed each time the header is delivered to the browser, aiding in the prevention of expiration.
The browser will not let the user access the website if a secure connection cannot be established. An error message will be displayed.
Enable HTTP Strict Transport Security in NGINX
A few simple steps are all that is required to implement HSTS on your server. For information on configuring the web server to use this directive, see the instructions listed below.
add_header Strict-Transport-Security “max-age=63072000; includeSubdomains; preload”;
Enable HTTP Strict Transport Security in Apache
Header always set Strict-Transport-Security “max-age=63072000; includeSubdomains; preload”
The HSTS response header can be checked by running a curl command:
curl -I https://alexbobes.com/main.css HTTP/1.1 301 Moved Permanently Server: nginx Date: Wednesday, 22 Jul 2022 04:07:45 GMT Content-Type: text/html Content-Length: 178 Connection: keep-alive Location: https://alexbobes.com/main.cssStrict-Transport-Security: max-age=31536000; includeSubdomains; preload
The bottom line is that implementing HTTP Strict Transport Security will help keep your website’s users safe. Insecure HTTP content can be delivered for a variety of reasons, but HSTS helps eliminate that risk, preventing communication interception by attackers.
With the Expect-CT header, websites can report and optionally enforce Certificate Transparency requirements, preventing the use of incorrectly issued certificates. Activating this header tells the browser to check the public CT logs for the certificate’s existence. The following is an example of a header:
Expect-CT: max-age=604800, enforce, report-uri=”https://alexbobes.com/learn”
Enable HTTP Strict Transport Security in NGINX
add_header Expect-CT “max-age=604800, enforce, report-uri=’https://alexbobes.com/learn’ always;
Enable HTTP Strict Transport Security in Apache
header always set Expect-CT “max-age=604800, enforce, report-uri=”https://alexbobes.com/learn“
This header prevents browsers like Internet Explorer and Google Chrome from detecting any response other than what is declared in the Content-Type declaration. Drive-by downloads are less likely, and the content is better taken care of as a result. Example of what the header looks like: X-Content-Type-Options: nosniff
Enable X-Content-Type-Options in NGINX
add_header X-Content-Type-Options “nosniff” always;
Enable X-Content-Type-Options in Apache
header always set X-Content-Type-Options “nosniff”
The Feature-Policy header can be used to allow or deny browser features in its own frame or content or within inline elements like the <iframe>. Feature-Policy headers allows web developers to control how APIs and web features behave in the browser by enabling or disabling them. The header looks like this: Feature-Policy: autoplay ‘none’; camera ‘none’
Enable Feature-Policy in NGINX
add_header Feature-Policy “autoplay ‘none’; camera ‘none'” always;
Enable Feature-Policy in Apache
header always set Feature-Policy “autoplay ‘none’; camera ‘none'”
8. Other Security Improvements for NGINX and Apache
Install ModSecurity for Your Web Server
ModSecurity is a free, open-source module acting like a web application firewall. Filtering, server identity masking, and null-byte attack prevention are some of its features. Real-time traffic monitoring is another feature provided by the module. Following the ModSecurity guide to install mod security will help you strengthen your security options.
Configure SSL and Cipher Suites
NGINX’s default configuration allows the use of insecure older versions of the TLS protocol (ssl protocols TLSv1 TLSv1.1 TLSv1.2 according to official documentation). Attacks like the BEAST attack could result as a result of this. Because of it, I advise you to stop using older TLS protocols and instead switch to newer, more secure TLS versions in your configuration.
Diffie-Hellman key exchange
Using Diffie-Hellman key exchange, even if attackers get their hands on your server’s private key, it will be exponentially more difficult for them to decipher communication between the server and its clients.
Navigate to /etc/ssl/certs/ and generate your DH with OpenSSL: openssl dhparam -out dhparam.pem 4096
Add the following to your Nginx configuration: ssl_dhparam /etc/ssl/certs/dhparam.pem;
Update Your Server Regularly
You should always keep your NGINX or APACHE web server up to date, just like you would with any other piece of software. The directory traversal vulnerability (CVE-2009-3898) that existed in NGINX versions prior to 0.7.63 and 0.8.x versions prior to 0.8.17 was fixed in recent updates. New security features and enhancements are frequently included in software updates as well. The nginx & apache websites have a dedicated section for security advisories, as well as news about the most recent updates.