Security Headers to use on your webserver

Introduction

Dozens of websites are hacked because of misconfiguration or a lack of protection.
You can indeed see on the OWASP Top 10, which are the Top 10 identified flaws on web servers and services from the OWASP (Open Web Application Security Project), that the Security Misconfiguration is the most identified cause of vulnerabilities on web services.
This is commonly a result of insecure default configurations, incomplete or ad-hoc configurations, open cloud storage, misconfigured HTTP headers, and verbose error messages containing sensitive information.
Not only must all operating systems, frameworks, libraries, and applications be securely configured, but they must be patched/upgraded in a timely fashion.
Let’s deep dive on the weaknesses and impacts of it.

Threat Agents / Attack Vectors
Security Weakness
Impacts

App Specific/Exploitability:3
Prevalence:3/Detectability:3
Technical:2/Business ?

Attackers will often attempt to exploit unpatched flaws or access default accounts, unused pages, unprotected files and directories, etc to gain unauthorized access or knowledge of the system.
Security misconfiguration can happen at any level of an application stack, including the network services, platform, web server, application server, database, frameworks, custom code, and pre-installed virtual machines, containers, or storage. Automated scanners are useful for detecting misconfigurations, use of default accounts or configurations, unnecessary services, legacy options, etc.
Such flaws frequently give attackers unauthorized access to some system data or functionality. Occasionally, such flaws result in a complete system compromise. The business impact depends on the protection needs of the application and data.

In this post, we are going to go through the headers and configuration you should use on your project in order to secure your server.
At first, we consider that all requests and responses are transmitted over https.
And that all the logging and information from the server configuration are hidden.
Before you start :

Don’t forget to backup your current configuration before making any change to your configuration.
Moreover some headers may not be compatible regarding on the browser. I encourage you to check out the browser compatibility on the compatibility matrix that is available on that page.
Mod-Headers must be enabled in Apache to implement these headers. Ensure the line is uncommented in httpd.conf file.

Let us review the HTTP headers list that we are going to cover :

X-XSS-Protection
X-Frame-Options

X-Content-Type-Options

Content-Security-Policy

Referrer-Policy

HTTP Strict Transport Security

SameSite

HttpOnly

Secure

Conclusion

Annexes

Note : If you want to have the sum up and the Apache and NGinx configurations, you can go to the “Conclusion".

1. X-XSS-Protection

The X-XSS-Protection header can prevent some level of XSS (CrosSite-Scripting) attacks.
XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

8
.
NS
4+
.
.
.

There are 4 possible ways you can configure that header.

Parameter Value
Meaning

0
XSS filter disabled

1
XSS filter enabled and sanitized the page if attack detected

1;mode=block
XSS filter enabled and prevented rendering the page if attack detected

1;report=http://example.com/report_URI

XSS filter enabled and reported the violation if attack detected

What we recommend to implement : 1;mode=block

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header set X-XSS-Protection "1; mode=block". Restart the apache to verify

NGinx
Add the following in nginx.conf under http block. add_header X-XSS-Protection "1; mode=block";. Nginx restart is needed to get this reflected on your web page response header.

2. X-Frame-Options

The X-Frame-Options header prevents Clickjacking vulnerability on your website.
By implementing this header, you instruct the browser not to embed your web page in frame/iframe.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

8
13
47
49
9.1
39
4.4

There are 3 possible ways you can configure that header.

Parameter Value
Meaning

SAMEORIGIN
Frame/iFrame of content is only allowed form the same site origin.

DENY
Prevent any domain to embed your content using frame/iframe.

ALLOW-FROM
Allow framing the content only on particular URI.

What we recommend to implement : DENY

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header always append X-Frame-Options DENY. Restart the apache to verify

NGinx
Add the following in nginx.conf under http block. add_header X-Frame-Options “DENY”;. Nginx restart is needed to get this reflected on your web page response header.

3. X-Content-Type-Options

The X-Content-Type-Options header prevents MIME types security risk by adding this header to your web page’s HTTP response. Having this header instruct browser to consider files types as defined and disallow content sniffing.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

8
.
51
1.0
NS
13
.

There are 1 possible way you can configure that header.

Parameter Value
Meaning

nosniff
Consider files types as defined and disallow content sniffing.

What we recommend to implement : nosniff

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header set X-Content-Type-Options nosniff. Restart the apache to get the configuration active and then verify.

NGinx
Add the following in nginx.conf under server block. add_header X-Content-Type-Options nosniff;. Nginx restart is needed to get this reflected on your web page response header.

4. Content Security Policy

The Content Security Policy prevent XSS, clickjacking, code injection attacks by implementing the Content Security Policy (CSP) header in your web page HTTP response.
CSP instruct browser to load allowed content to load on the website.
Nevertheless, if you implement CSRF, in some framework (like AngularJS) the browser retrieves the CSRF cookie and add a custom header XSRF-HEADER to the response in order to implement a CSRF prevention method. So you have to be very careful about how you implement that header. You can find a lot of great methods to prevent CSRF on the OWASP website.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

11
13
47
49
9.1
39
4.4

There are 23 possible ways you can configure that header.

Parameter Value
Meaning

base-uri
Define the base uri for relative uri.

default-src
Define loading policy for all resources type in case of a resource type dedicated directive is not defined (fallback).

script-src
Define which scripts the protected resource can execute.

object-src
Define from where the protected resource can load plugins.

style-src
Define which styles (CSS) the user applies to the protected resource.

img-src
Define from where the protected resource can load images.

media-src
Define from where the protected resource can load video and audio.

frame-src
Deprecated and replaced by child-src.

child-src
Define from where the protected resource can embed frames.

frame-ancestors
Define from where the protected resource can be embedded in frames.

font-src
Define from where the protected resource can load fonts.

connect-src
Define which URIs the protected resource can load using script interfaces.

manifest-src
Define from where the protected resource can load manifest.

form-action
Define which URIs can be used as the action of HTML form elements.

sandbox
Specifies an HTML sandbox policy that the user agent applies to the protected resource.

script-nonce
Define script execution by requiring the presence of the specified nonce on script elements.

plugin-types
Define the set of plugins that can be invoked by the protected resource by limiting the types of resources that can be embedded.

reflected-xss
Instructs 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 X-XSS-Protection header.

block-all-mixed-content
Prevent user agent from loading mixed content.

upgrade-insecure-requests
Instructs user agent to download insecure resources using HTTPS.

referrer
Define information user agent must send in Referer header.

report-uri (deprecated)
Specifies a URI to which the user agent sends reports about policy violation.

report-to
Specifies a group (defined in Report-To header) to which the user agent sends reports about policy violation.

What we recommend to implement : default-src on self with reporting enabled

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header set Content-Security-Policy: default-src ‘self’; report-uri http://reportcollector.example.com/collector.cgi. Restart the apache to get the configuration active and then verify.

NGinx
Add the following in nginx.conf under server block. add_header Content-Security-Policy "default-src ‘self’;", "report-uri http://reportcollector.example.com/collector.cgi;"". Nginx restart is needed to get this reflected on your web page response header.

5. Referrer Policy

The Referrer-Policy HTTP header governs which referrer information, sent in the Referer header, should be included with requests made.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

NS
NS
50
56
NS
43
.

There are 8 possible ways you can configure that header.

Parameter Value
Meaning

no-referrer
The Referer header will be omitted entirely.

no-referrer-when-downgrade
This is the user agent’s default behavior if no policy is specified.

origin
Only send the origin of the document as the referrer in all cases.

origin-when-cross-origin
Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.

same-origin
A referrer will be sent for same-site origins, but cross-origin requests will contain no referrer information.

strict-origin
Only send the origin of the document as the referrer to a-priori as-much-secure destination (HTTPS->HTTPS), but don’t send it to a less secure destination (HTTPS->HTTP).

strict-origin-when-cross-origin
Send a full URL when performing a same-origin request, only send the origin of the document to a-priori as-much-secure destination (HTTPS->HTTPS), and send no header to a less secure destination (HTTPS->HTTP).

unsafe-url
Send a full URL (stripped from parameters) when performing a a same-origin or cross-origin request.

What we recommend to implement : no-referrer

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header set Referrer-Policy "no-referrer". Restart the apache to get the configuration active and then verify.

NGinx
Add the following in nginx.conf under server block. add_header Referrer-Policy no-referrer;. Nginx restart is needed to get this reflected on your web page response header.

6. HTTP Strict Transport Security

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.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

11
13
47
49
9.1
39
4.4

There are 2 possible ways you can configure that header.

Parameter Value
Meaning

max-age=SECONDS
The time, in seconds, that the browser should remember that this site is only to be accessed using HTTPS.

includeSubDomains
If this optional parameter is specified, this rule applies to all of the site’s subdomains as well.

What we recommend to implement : max-age=31536000; includeSubDomains

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header set Strict-Transport-Security "max-age=31536000; includeSubDomains". Restart the apache to get the configuration active and then verify.

NGinx
Add the following in nginx.conf under server block. add_header Strict-Transport-Security ‘max-age=31536000; includeSubDomains’;. Nginx restart is needed to get this reflected on your web page response header.

7. Cookies

When receiving an HTTP request, a server can send a Set-Cookie header with the response. The cookie is usually stored by the browser, and then the cookie is sent with requests made to the same server inside a Cookie HTTP header. An expiration date or duration can be specified, after which the cookie is no longer sent. Additionally, restrictions to a specific domain and path can be set, limiting where the cookie is sent.

The Set-Cookie and Cookie headers

The Set-Cookie HTTP response header sends cookies from the server to the user agent.
A simple cookie is set like this Set-Cookie: =<cookie-value>.

Session cookies

The cookie created above is a session cookie: it is deleted when the client shuts down, because it didn’t specify an Expires or Max-Age directive. However, web browsers may use session restoring, which makes most session cookies permanent, as if the browser was never closed.

Permanent cookies

Instead of expiring when the client closes,permanent cookies expire at a specific date (Expires) or after a specific length of time (Max-Age). Permanent cookies are set like this Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2020 07:28:00 GMT;.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

.
.
.
.
.
.
.

There are many possible cookies you can add to improve the security of your product.

"SameSite" Cookie

SameSite cookies let servers require that a cookie shouldn’t be sent with cross-site requests, which somewhat protects against cross-site request forgery attacks (CSRF). SameSite cookies are still experimental and not yet supported by all browsers.
The same-site attribute can have one of two values:
|Value|Meaning|
|—|—|
|strict|If a same-site cookie has this attribute, the browser will only send cookies if the request originated from the website that set the cookie. If the request originated from a different URL than the URL of the current location, none of the cookies tagged with the strict attribute will be included.|
|lax|If the attribute is set to lax, same-site cookies are withheld on cross-domain subrequests, such as calls to load images or frames, but will be sent when a user navigates to the URL from an external site, for example, by following a link.|
The default behavior if the flag is not set, or not supported by the browser, is to include the cookies in any request, including cross-origin requests.

"Secure" Cookie

A secure cookie is only sent to the server with an encrypted request over the HTTPS protocol. Even with Secure, sensitive information should never be stored in cookies, as they are inherently insecure and this flag can’t offer real protection. Starting with Chrome 52 and Firefox 52, insecure sites (http:) can’t set cookies with the Secure directive.

"HttpOnly" Cookie

To prevent cross-site scripting (XSS) attacks, HttpOnly cookies are inaccessible to JavaScript’s Document.cookie API; they are only sent to the server. For example, cookies that persist server-side sessions don’t need to be available to JavaScript, and the HttpOnly flag should be set.

What we recommend to implement : Secure=True; HttpOnly=True, SameSite=strict

Apache

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Strict. Restart the apache to get the configuration active and then verify.

Apache HTTP Server lower than Aache 2.2.4
Add the following entry in httpd.conf of your Apache web server. Header set Set-Cookie HttpOnly;Secure;SameSite=Strict. Restart the apache to get the configuration active and then verify.

PHP

setcookie ( string $key [, string $value = "" [, int $expires = 0 [, string $path = "" [, string $domain = "" [, bool $secure = FALSE [, bool $httponly = FALSE ]]]]]] ) : bool

Node.JS

response.setHeader(‘Set-Cookie’, ‘key=value; secure; HttpOnly; SameSite=Strict’);

Python

self.set_secure_cookie(‘key’, value, secure=True, httponly=True)

Ruby on Rails

cookies["key"] = { :value => "value", :secure => true, :http_only => true, :same_site => }

Then you can test your website http response header against that website.

Conclusion

Let’s sum up the server configuration you can use.

Apache

Header
Implementation

X-XSS-Protection
Header set X-XSS-Protection "1; mode=block"

X-Frame-Options
Header set X-Frame-Options "DENY"

X-Content-Type-Options
Header set X-Content-Type-Options "nosniff"

Content-Security-Policy
Header set Content-Security-Policy: default-src ‘self’; report-uri http://reportcollector.example.com/collector.cgi

Referrer-Policy
Header set Referrer-Policy "no-referrer"

HTTP Strict Transport Security
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"

Nginx

Header
Implementation

X-XSS-Protection
add_header X-XSS-Protection "1;mode=block";

X-Frame-Options
add_header X-Frame-Options "DENY";

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

Content-Security-Policy
add_header Content-Security-Policy "default-src ‘self’;", "report-uri http://reportcollector.example.com/collector.cgi;"

Referrer-Policy
add_header Referrer-Policy no-referrer;

HTTP Strict Transport Security
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";

Cookies

Server type
How to

Apache HTTP Server
Add the following entry in httpd.conf of your Apache web server. Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure;SameSite=Strict. Restart the apache to get the configuration active and then verify.

Apache HTTP Server lower than Aache 2.2.4
Add the following entry in httpd.conf of your Apache web server. Header set Set-Cookie HttpOnly;Secure;SameSite=Strict. Restart the apache to get the configuration active and then verify.

Browser Support

Internet Explorer
Edge
Firefox
Chrome
Safari
Opera
Android

HTTP Strict Transport Security (HSTS)
11
13
47
49
9.1
39

Public Key Pinning Extension for HTTP (HPKP)
NS
NS
47
49
NS
39

X-Frame-Options
8
13
47
49
9.1
39

X-XSS-Protection
8
.
NS
4+
.
.

X-Content-Type-Options
8
.
51
1.0
NS
13

Content-Security-Policy
11
13
47
49
9.1
39

X-Permitted-Cross-Domain-Policies
.
.
.
.
.
.

Referrer-Policy
NS
NS
50
56
NS
43

Expect-CT
.
.
.
61
.
48

Feature-Policy
.
.
.
.
.
.

Annexes

OWASP Secure Headers Project – OWASP
HTTP Cookies Security – Mozilla Developer Network

Link: https://dev.to/shosta/security-headers-to-use-on-your-webserver-3id5