Security headers can effectively prevent a variety of hacking attempts. You should consider headers like Strict-Transport-Security, Content-Security-Policy, X-Frame-Options or X-XSS-Protection.
Security Assessment
CVSS Vector: AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
Vulnerability Information
Security headers can effectively prevent a variety of hacking attempts. You should consider headers like Strict-Transport-Security, Content-Security-Policy, X-Frame-Options or X-XSS-Protection.
Guides
Use the following guides to set correct security headers for your web application:
- Webserver Configuration (Apache, nginx)
- HTTP Strict Transport Security (HSTS)
- X-Frame-Options
- X-XXS-Protection
- X-Content-Type-Options
- Same-Site Cookie
- Content-Security-Policy
- Referrer-Policy
- Access-Control-Allow-Origin
Webserver Configuration
To configure your webserver to contain all described headers, use the following configurations. Below, you find further descriptions of the single headers.
Apache
On Apache you need to update your configuration to include the correct header directives. Add this to the virtual host configuration in /etc/apache2/sites-enabled/domain.conf or /etc/httpd/sites-enabled/domain.conf:
<VirtualHost *:443>
Header always set Strict-Transport-Security "max-age=31536000"
Header always set X-Frame-Options "deny"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Content-Security-Policy "default-src 'self'"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</VirtualHost>
nginx
On Nginx you need to update your configuration file which is usually located at /etc/nginx/nginx.conf, /etc/nginx/sited-enabled/yoursite.com (Ubuntu / Debian) or /etc/nginx/conf.d/nginx.conf (RHEL / CentOS) to include the correct header with the add_header directives:
server {
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains;" always;
add_header X-Frame-Options "deny" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'self'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
HTTP Strict Transport Security (HSTS)
The HSTS header enforces HTTPS connections. This prevents downgrade attacks to an insecure HTTP connection. See Enable HSTS for the correct settings.
X-Frame-Options
The X-Frame-Options header declares whether this site may be embedded as a frame into other websites. The values are:
Value | Effect |
deny | Do not allow frames of this site |
sameorigin | Allow frames of this site when the domain matches |
allow-from DOMAIN | Allow frames of this site when embedded in webpages on DOMAIN |
Setting this header e.g. to deny will protects the website against clickjacking attacks where an attacker overlays an iframe of your webpage with arbitrary content to bait his victims in clicking on certain links on your website.
X-XXS-Protection
Some web browsers are shipped with a Cross-Site-Scripting (XSS) filter. This filter can detect certain XSS attacks and prevent them. To configure the browser filter behaviour, use the X-XSS-Protection header.
Value | Effect |
0 | Disable the filter |
1 | Enable the filter to sanitize the webpage in case of an attack |
1; mode=block | Enable the filter to block the webpage in case of an attack |
Setting this header e.g. to 1; mode=block will tell the browser that it should not render the webpage in case that it detects an attack.
X-Content-Type-Options
Browsers try to detect the MIME-type of files that are sent by the webserver. If an attacker manages to upload a malicious (executable) file to a webserver, which only sends images, the MIME-type can provide some protection, as it tells the browser that it should expect an image and not an executable file. Therefore, the browser must not try to detect the MIME-type, but only use the webserver provided MIME-type. To enforce this behaviour, use the X-Content-Type-Options header and set it to nosniff.
Value | Effect |
nosniff | Only use the declared MIME-type |
Same-Site Cookie
The Same-Site cookie flag tells the browser to not send cookies along with cross-site requests. This cookie flag prevents the risk of cross-site information leakage and can also help to mitigate Cross-Site Request Forgery attacks. Possible values are Strict, Lax or None. In case the Same-Site cookie flag is set to None the Secure flag must be set, to prevent sending the cookie in an insecure context.
Value | Effect |
None | The cookie will be sent in all contexts. |
Lax | The cookie is sent when a user follows a link into your site. But the cookie is not sent when content of your site is included in a third party site. |
Strict | Prevent the cookie from being sent to the target site in all cross-site requests, even when following a link into your site. |
Content-Security-Policy
The Content-Security-Policy (CSP) header tells the browser from which domain further resources such as scripts, images or stylesheets may be loaded. This can prevent various Cross-Site-Scripting (XSS) and other Cross-Site-Injection attacks. The policy needs to be hand-crafted for the particular usage, as it may easily prohibit analytic scripts, fonts, or other resources that are loaded from a third party.
Value | Effect |
default-scr 'self' resources.example.org | Define loading all resource types from the own domain and resources.example.org |
script-src 'self' scripts.example.org | Enable loading scripts from the own domain and scripts.example.org |
object-src 'none' | Disallow loading of all objects such as <applet>, <embed> and <object> |
style-src 'self' style.example.org | Enable loading stylesheets from the own domain and style.example.org |
img-src 'self' imgs.example.org | Enable loading images from the own domain and imgs.example.org |
media-scr 'self' media.example.org | Enable loading media elements from the own domain and media.example.org |
child-src 'self' | Define that in <frame> and <iframe> elements only pages from the own domain may be loaded |
font-src 'self' fonts.example.org | Enable loading fonts from the own domain and fonts.example.org |
connect-src 'self' api.example.org | Enable connections via script interfaces such as XMLHttpRequest or WebSocket to the own domain and api.example.org |
manifest-src 'self' | Enable loading manifests from the own domain |
frame-ancestors 'self' | Define that this page may only be used as a frame on pages of the own domain |
form-action 'self' | Ensures that form actions can only be of the own domain |
sandbox | Enables a sandbox that blocks most actions on the page. More Information: CSP: sandbox |
plugin-types application/x-java-applet |
Allows to embed an <applet>. This only works if object-src is not set to 'none' |
block-all-mixed-content | Prevents browser to load mixed content (such as http and https mixed elements) |
upgrade-insecure-requests | Download all resources via an https connection |
A very simple and restrictive policy can be: default-src 'self'. Make sure to test your configuration thoroughly as you may not want to block your analytics script or other third party resources.
Referrer-Policy
The Referrer-Policy header defines how much information about the referrer is sent when the user clicks on a link. The referrer may leak sensitive information such as user-specific URLs. Therefore the referrer-policy might be set to some more restrictive value. A relatively secure setting is strict-origin-when-cross-origin.
Value | Effect |
no-referrer | Do not include any referrer information on requests |
no-referrer-when-downgrade | Do not send the referrer when the actual connection is a https request and the new request is http |
origin | Send the origin as referrer but do not include any path information |
origin-when-cross-origin | Send the origin as referrer when the new request is on another domain and all information for same-origin cases |
same-origin | Send the referrer only when the request stays in the current domain |
strict-origin | Send the origin as referrer, but only when the request is no downgrade from https to http |
strict-origin-when-cross-origin | Send the origin as referrer to cross-origin requests and the full referrer on same-origin requests but only when the request is no downgrade |
unsafe-url | Always send the full URL as referrer |
Cache-Control
The Cache-Control header defines how caching in the browser is configured. Depending on the value of the header, the browser may cache the website including any sensitive information. For pages, where confidentiality is an issue, the header should be set to no-store.
Value | Effect |
must-revalidate | The cache must revalidate the state of the resource before using it |
no-cache | Send the request even if the cache has stored the resource |
no-store | Do not store the resource in any cache |
no-transform | Do not transform the resource (e.g. change image format to store cache space) |
public | Allow to store the resource in any cache |
private | Allow to store the resource in a user-specific cache, but not an a shared cache |
proxy-revalidate | Same as must-revalidate for shared caches |
max-age=<seconds> | Configure the time for which the resource will be treated as fresh |
s-maxage=<seconds> | Overwrite a max-age or Expires header, but is only used for shared caches |
Access-Control-Allow-Origin
The Access-Control-Allow-Origin Header defines, which applications may consume your API. Consider this article It should be set to the domain of you frontend, such as:
Access-Control-Allow-Origin: https://example.org
If you have multiple applications using your API, please consult this blog article.