Sunteți pe pagina 1din 8

HTTP Security Headers with Nginx

28 NOVEMBER 2018 on ​Hosting & Cloud​, ​Security


Introduction
There are several web application threats that manifest themselves in the client's browser. We can defend
against these on the server side but the execution of the attack happens in the client's browser. HTTP
security headers can help mitigate some of the threats by instructing the client's browser on how to handle
our website's content and connections to the server.

HTTP Headers
HTTP is the language of the web. Clients and servers communicate with each other using HTTP. HTTP
messages can contain one or more optional headers that allow the client and the server to pass additional
information with the request or the response.

You can inspect the request/response headers within the browser by visiting a web page and opening the
browser console (​Ctrl+Shift+K​ on Firefox, ​Ctrl+Shift+J​ on Chrome) and clicking on the ​Network
tab.

Note that on visiting the homepage of Attosol at ​http://www.attosol.com​, the server responds with a ​301
(Moved Permanently)​ status code and sets the ​Location​ header to ​https://www.attosol.com​, forcing
the browser to make the request again using HTTPS.

Nginx
Nginx can be configured to set response headers by modifying the server blocks in the configuration files.

Add Header Directive


The ​add_header​ directive sets response headers.

add_header X-Content-Type-Options "nosniff" always;

Here, we set the ​X-Content-Type-Options​ header, used to protect against MIME sniffing
vulnerabilities. The ​always​parameter ensures that the header is set for all responses, including internally
generated error responses.

Header Inheritance
Generally, you place the ​add_header​ directive in the top‑level s ​ erver​ block. When you do this, Nginx
will ignore the headers from the parent block. Similarly, if a ​location​ includes an ​add_header​ directive
itself, it does not inherit headers from enclosing ​server​ block. When you specify a header inside a child
block, you need to re-declare all ​add_header​ directives from the parent block inside the child block again.

HTTP Strict Transport Security (HSTS)


When a browser requests a page manually without an explicit ​http://​, the server responds in cleartext. A
secure server must immediately send a redirect response to ensure that all further requests happen on
https://​ connection. However, even this approach is vulnerable to Man-in-the-Middle attacks for a well
placed attacker. An attacker could intercept the request and redirect the client to a different page, stealing
the user's information. ​Modern web applications need to be deployed over HTTPS.​ If you haven't set up
your web server to use SSL till now, ​here's a guide for that​.

HSTS is a way to deal with this potential vulnerability by instructing the browser that a domain can only be
accessed using HTTPS. If the user enters or uses an HTTP link, the browser strictly upgrades the
connection to HTTPS:

Setting the HSTS header

On receiving the HSTS header from a website, the browser will prevent any further communication to that
website over HTTP and will use HTTPS instead. We can configure nginx to set the HSTS header on every
response using the ​add_header​ directive.

server {
listen 80;
listen [::]:80;

server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;

ssl_certificate path_to/fullchain.pem;
ssl_certificate_key path_to/privkey.pem;
include path_to/options-ssl-nginx.conf;
ssl_dhparam path_to/ssl-dhparams.pem;
root /var/www/html/your_app;

index index.html;

server_name your_domain;

location / {
try_files $uri $uri.html $uri/ =404;
}

add_header Strict-Transport-Security "max-age=31536000;


includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
}

When a browser sees this header from an HTTPS website, it “learns” that this domain must only be
accessed using HTTPS.​ It caches this information for the ​max-age​ period (typically 31,536,000 seconds,
equal to about 1 year). On initially testing HSTS, it is recommended to start with very small values for the
max-age​ timeout.

The optional ​includeSubDomains​ parameter tells the browser that the HSTS policy also applies to all
subdomains of the current domain. Check the image below and notice the Status code 307.

The previous requests follows with a regular redirect, and you can find the Strict-Transport-Security header
in the next request as follows (we have kept the age to 1 day or 86400 seconds only for demonstration
purpose):
HSTS Preload
You can only set the HSTS header over HTTPS. HSTS works with a trust-on-first-use assumption. To
eliminate this and to force HTTPS even on the very first request, you can submit your domain to a ​preload
list​. Preload lists are hard-coded into the browsers, ensuring that even the very first request would be made
over HTTPS.

Content Security Policy


The CSP header is a way of whitelisting the things that your site is allowed to run. This includes images,
stylesheets, javascript, inline styles, frames.

Content-Security-Policy: policy

CSP makes it possible to reduce or eliminate the vectors by which XSS can occur by specifying the
domains that the browser should consider to be valid sources of executable scripts. A CSP compatible
browser will then only run scripts loaded in source files received from those whitelisted domains.

Policy

The policy is a list of whitelisted sources for content on the website. Check out the results of setting a CSP
on a website.

Content-Security-Policy: default-src 'self'


A policy contains one or more directives, with each directive followed by a space separated list of allowed
origins. The directives are separated by a semi-colon.

default-src​ directive defines valid sources for fonts, images, media, scripts and styles. ​self​ matches
the scheme, port and origin of the document it is served with. The browser effectively blocked loading of all
external stylesheets and scripts.

Let's modify this directive to allow the blocked content with the new CSP.

Content-Security-Policy: default-src 'self' https://code.jquery.com


https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com;
Our content now loads properly with the
new CSP in place.

Fine Grained Controls

One major feature of CSP is the granularity of the controls that it allows. To further lock down our CSP
while allowing the required content on our page, we could rewrite our policy, disallowing images/videos,
frames.

Content-Security-Policy: script-src 'self' https://code.jquery.com


https://cdnjs.cloudflare.com https://stackpath.bootstrapcdn.com; style-src
https://stackpath.bootstrapcdn.com;

script-src​, ​style-src​ are some of the directives that help define the policy with higher granularity.
Checkout this ​CSP Cheat Sheet​ to learn more about the CSP directives.

CSP Reporting

CSP can be tested in a report-only mode or deployed in production with violation reporting.

Content-Security-Policy-Report-Only: <policy-directive>; <policy-directive>


Content-Security-Policy: default-src 'self'; report-uri
https://reportcollector.example.com/collector

You can configure your own back-end service to handle the incoming reports. Also, ​report-uri.com​ provides
a free CSP report collection service.

Nginx Configuration with CSP Header

Let's check out our final Nginx configuration.

server {
listen 80;
listen [::]:80;

server_name example.com;
return 301 https://$server_name$request_uri;
}
server {

listen [::]:443 ssl ipv6only=on;


listen 443 ssl;

ssl_certificate path_to/fullchain.pem;
ssl_certificate_key path_to/privkey.pem;
include path_to/options-ssl-nginx.conf;
ssl_dhparam path_to/ssl-dhparams.pem;

root /var/www/html/your_app;

index index.html;

server_name your_domain;

location / {
try_files $uri $uri.html $uri/ =404;
}

add_header Strict-Transport-Security "max-age=31536000;


includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'
https://code.jquery.com https://cdnjs.cloudflare.com
https://stackpath.bootstrapcdn.com;";

add_header X-Content-Type-Options "nosniff" always;


add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;

}
Other Headers
Note the 3 new headers added in the configuration file shown above.

add_header X-Content-Type-Options "nosniff" always;


add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;

The ​X-Frame-Options​ header can help prevent click-jacking attacks. This header indicates whether the
web page can be rendered in a ​<frame>​.

The ​X-XSS-Protection​ header is used to ensure that the browser's XSS Protection filter is turned on.

While these headers provide protection in older browsers, implementing a strong Content-Security-Policy
covers much more ground.

Parting words
The web platform offers a wide variety of tools and techniques for security. ​securityheaders.io​ is a very
helpful tool that you can use to check if your web server is setting the headers properly. We covered
techniques to mitigate a few threats to web applications. Stay safe!

By Ramit Mittal, Associate Software Engineer, Attosol Technology

S-ar putea să vă placă și