In this post, I am going to show you, how to increase the security of your webpage for your visitors. We will configure Apache to add more information in the HTTP header, which helps the browser to identify and block potential attacks.
I will start with talking about each single HTTP header item, that will help increasing the security, without any references to how to configure Apache to support it. After going through all of them, we will configure all the feature together. So if you are here just for the result, you can jump right to the next chapter instead of going through the following subchapters.
#1 Content-Security-Policy (CSP)
The main purpose of this item is to prevent cross-site scripting (XSS) and other code injection attacks. By providing clear instructions and restrictions, you help the browser to block unwanted script execution and ultimately XSS attacks. The following item in the HTTP header would instruct the browser to only load resources from the same origin including URL scheme and port number.
Content-Security-Policy: default-src 'self'
Instead of ‘self’, you could use ‘unsafe-inline’, ‘unsafe-eval’ or other values (checkout this article). ‘unsafe-inline’ would mean, that the browser can run inline scripts.
Beside the default-src, there are many others such as script-src, style-src and so on. As the name success the default-src act as a fallback directive. E.g. If you don’t instruct anything specific for scripts, it will fall back to default-src. Check out this article to see the full list of all directives.
This item follows the whitelist approach. So if you do not specified explicitly then it is not allowed. Be as restrictive as possible.
Before the W3C published the standard, “X-Content-Security-Policy” and “X-WebKit-CSP” were used. But major modern browser has now switched to the W3C standard “Content-Security-Policy”. To check the browser support of CSP, click here.
This item is used to counter clickjacking, where a malicious website shows your website in an frame element and put a transparent overlay over it. When a user intents to click something on your page, the overlay would be activated instead.
By adding it to the HTTP header, you instruct the browser, that it should allow a page to be rendered inside a frame (<frame>, <iframe>, <embed> or <object>). Possible values are:
X-Frame-Options: deny X-Frame-Options: sameorigin X-Frame-Options: allow-from https://blog.draphony.com/
Although with the frame-ancestors directives of the CSP, this directive is obsolete. But for backward compatibility you should still have it.
Starting with IE8, Microsoft introduced a built-in feature known as XSS filter to mitigate reflected XSS. Later Webkit introduced a similar feature for Chrome and Safari. The idea is quite straightforward, the browser check whether a script, that it is about to run is also present in the request, that fetched that web page. If it is the case, it is a strong indication.
Depends on the following settings, the browser will act accordingly:
X-XSS-Protection: 0 X-XSS-Protection: 1 X-XSS-Protection: 1; mode=block
0 means, disabling the feature. 1, the default, would instruct the browser to remove the unsafe parts. And the last option is to completely block the rendering of the document. It is recommended based on previous vulnerabilities, to use the “all or nothing” strategy meaning last option.
Mozilla does not offer any similar feature because it believes, that having a good content security policy makes this feature unnecessary (see Mozilla documentation).
This is another HTTP header extension, that is introduced by Microsoft and later implemented by other vendors. It instructs the browser to follow the MIME type and do not change it.
If the MIME type is not correct, block the request. Safari does not support this item (see Mozilla documentation).
The Strict-Transport-Security header item (often abbreviated as HSTS) instructs the browser that it should stick to the HTTPS, instead of using the HTTP. Currently the following options are available:
Strict-Transport-Security: max-age=<seconds> Strict-Transport-Security: max-age=<seconds> ; includeSubDomains Strict-Transport-Security: max-age=<seconds> ; preload Strict-Transport-Security: max-age=<seconds> ; includeSubDomains; preload
The first time, you visit a website using https with this item in the HTTP header, the browser will store this information. Every subsequent calls will automatically use HTTPS. Every visit to the page reset the age. Google is maintaining an HSTS preload service, which all browsers have stated the intent to use or are actually using.
By instructing the browser to stick to HTTPS, the user is less exposed to a man in the middle attack. You can register your page by clicking here.
#6 Securing Cookie
To enhance the security of cookies, you can add several directives to the Set-Cookie items:
Set-Cookie: <cookie-name>=<cookie-value>; Secure Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
You can use multiple directives at the same time:
Set-Cookie: <cookie-name>=<cookie-value>; Secure; HttpOnly; SameSite=Strict
The Secure directive instruct the browser to only share this cookie with HTTPS pages.
The SameSite directive instruct the browser, that it should not send the cookie along with cross-site requests. Hence, providing some protection against cross-site request forgery attacks (CSRF).
Configure Apache (>=2.2.4)
First you need to ensure, that your Apache web server has the header module enabled. If this is not the case, you can enable it using the following command:
sudo a2enmod headers
If you are not sure, just run it. It won’t harm. Afterwards, open your Apache configuration file or .htaccess file of your website and try to search for section <IfModule mod_headers.c> inside of it. Change it to
For most of the item, we use Header set, which means that any existing values will be replaced. Whereas Header edit will transform the information and Header append will append the information (see Apache documentation)
If you add the security to an existing web server, shared server or if you use CMS like WordPress, you will need to be less restrictive about the CSP. For WordPress, you may end up in something like this:
Header set Content-Security-Policy "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' 'self' https://gist.github.com https://cdn.jsdelivr.net; style-src 'unsafe-inline' 'self' https://fonts.googleapis.com https://github.githubassets.com https://cdn.jsdelivr.net; font-src 'self' data: https://fonts.gstatic.com; object-src 'none'; frame-src 'self' https://wp-themes.com; worker-src 'none';img-src 'self' data: blob: https://secure.gravatar.com https://assets-cdn.github.com https://*.w.org; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; connect-src 'self'"
This would allow you to use Gist and Google Fonts.
After completing the setup, you should use the online check tools from Mozilla to see your configuration and got additional hints. Click here to get there.