Implementing Security Headers
1. Enabling Headers Module
| Directive | Description | Default | Context | Override |
|---|---|---|---|---|
| LoadModule | Loads the headers module into the server | None | Server config | None |
Note: On some systems, the module might be located at
modules/mod_headers.so or mod_headers.so. Ensure the path matches your installation.
2. Configuring HTTP Strict Transport Security
| Directive | Values | Description |
|---|---|---|
| Strict-Transport-Security | max-age=31536000; includeSubDomains |
Enforces HTTPS and specifies the duration (in seconds) that the browser should remember to only use HTTPS. includeSubDomains applies the policy to all subdomains. |
| Strict-Transport-Security | max-age=31536000; includeSubDomains; preload |
Same as above but includes the preload directive to indicate that the site should be included in browsers' HSTS preload list. |
Example: Setting HSTS in Apache
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</VirtualHost>
Note: The
max-age value is in seconds. A value of 31536000 equals one year.
Warning: Once HSTS is enabled, it can be difficult to revert. Make sure the configuration is correct before deploying.
3. Setting X-Frame-Options Header
| Directive | Values | Description |
|---|---|---|
| Header | X-Frame-Options |
Controls whether the browser should be allowed to render a page in a frame, iframe, or object |
Example: Configuring X-Frame-Options
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
</IfModule>
Example: X-Frame-Options with ALLOW-FROM
<IfModule mod_headers.c>
Header always set X-Frame-Options "ALLOW-FROM https://trusted-site.com"
</IfModule>
Note: The
ALLOW-FROM option is deprecated in modern browsers and should be avoided in favor of CSP frame-ancestors directive.
X-Frame-Options Values
DENY- The page cannot be displayed in a frame, regardless of the site attempting to do soSAMEORIGIN- The page can only be displayed in a frame on the same origin as the page itselfALLOW-FROM uri- The page can only be displayed in a frame on the specified origin (deprecated)
4. Configuring X-Content-Type-Options
| Directive | Values | Description |
|---|---|---|
| Header set X-Content-Type-Options | nosniff |
Prevents browsers from attempting to guess the content type and forces strict MIME type checking. |
Example: Setting X-Content-Type-Options
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
</IfModule>
Note: The
X-Content-Type-Options header is particularly effective in preventing MIME type sniffing attacks, which can lead to XSS vulnerabilities.
5. Setting X-XSS-Protection Header
| Directive | Values | Description |
|---|---|---|
| Header set X-XSS-Protection | "1; mode=block" |
Enables the XSS filter and blocks pages from loading if an XSS attack is detected |
Example: Setting X-XSS-Protection Header
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
</IfModule>
Note: The
X-XSS-Protection header is deprecated in modern browsers and should be replaced with X-Content-Type-Options for better security.
6. Implementing Content Security Policy
| Directive | Description | Values | Notes |
|---|---|---|---|
| default-src | Sets the default source for various directives | 'self', 'none', 'unsafe-inline', 'unsafe-eval', URLs |
Used as fallback for other directives if not specified |
| script-src | Controls script sources | 'self', 'unsafe-inline', 'unsafe-eval', URLs |
Must include 'unsafe-inline' to allow inline scripts |
| style-src | Controls CSS sources | 'self', 'unsafe-inline', URLs |
Allows inline styles if 'unsafe-inline' is included |
| img-src | Controls image sources | 'self', 'data:', URLs |
Allows loading images from data URIs |
| font-src | Controls font sources | 'self', URLs |
Allows loading fonts from external sources |
| connect-src | Controls sources for fetch, XMLHttpRequest, etc. | 'self', URLs |
Prevents unauthorized API calls from the client |
| frame-src | Controls sources for embedded frames | 'self', URLs |
Prevents embedding content from untrusted sources |
| media-src | Controls media sources (audio, video) | 'self', URLs |
Restricts media from external sources |
| object-src | Controls sources for <object>, <embed>, and <applet> |
'self', 'none', URLs |
Prevents loading plugins from external sources |
| base-uri | Controls base URLs | 'self', URLs |
Prevents changing the base URL in HTML documents |
Example: Basic CSP Header
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'self'; media-src 'self'; object-src 'none'; base-uri 'self';"
Example: CSP with Reporting
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'self'; media-src 'self'; object-src 'none'; base-uri 'self'; report-uri /csp-report"
Note: The
Content-Security-Policy header should be set using the Header directive in Apache configuration or via a module like mod_headers.
Warning: Incorrectly configured CSP policies can break your site. Always test in a development environment before deploying to production.
7. Configuring Referrer-Policy Header
| Policy | Description | Usage |
|---|---|---|
| no-referrer | Does not send the Referer header | <meta name="referrer" content="no-referrer"> |
| no-referrer-when-downgrade | Default policy; sends referrer only when upgrading from HTTP to HTTPS | <meta name="referrer" content="no-referrer-when-downgrade"> |
| origin | Sends only the origin part of the referring URL | <meta name="referrer" content="origin"> |
| origin-when-cross-origin | Sends full referrer for same-origin requests, origin for cross-origin | <meta name="referrer" content="origin-when-cross-origin"> |
| same-origin | Sends full referrer for same-origin, none for cross-origin | <meta name="referrer" content="same-origin"> |
| strict-origin | Sends only the origin when upgrading from HTTP to HTTPS, otherwise none | <meta name="referrer" content="strict-origin"> |
| strict-origin-when-cross-origin | Full referrer for same-origin, origin for cross-origin, strict-origin for upgrades | <meta name="referrer" content="strict-origin-when-cross-origin"> |
| unsafe-url | Sends full referrer URL (including query strings and fragments) | <meta name="referrer" content="unsafe-url"> |
Example: Setting Referrer-Policy via Apache Config
<IfModule mod_headers.c>
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Note: The
Referrer-Policy header is supported in all modern browsers and can be set using either the meta tag or server headers.
8. Setting Permissions-Policy Header
| Directive | Values | Description |
|---|---|---|
| permissions-policy | geolocation=(self "https://example.com") |
Controls which features and APIs can be used in the context of a document or worker |
| permissions-policy | camera=(), microphone=() |
Disables camera and microphone access |
Example: Setting Permissions-Policy Header
<IfModule mod_headers.c>
Header set Permissions-Policy "geolocation=(self ""https://example.com""), camera=(), microphone=()"
</IfModule>
Note: The Permissions-Policy header allows fine-grained control over browser features and APIs, enhancing security by restricting access to sensitive capabilities.
9. Using Expect-CT Header
| Directive | Description | Values | Notes |
|---|---|---|---|
| Expect-CT | Enforces Certificate Transparency | max-age=86400, enforce, report-uri="https://example.com/ct-report" |
Used to enforce CT policy compliance for certificates |
Example: Configuring Expect-CT Header
<IfModule mod_headers.c>
Header always set Expect-CT "max-age=86400, enforce, report-uri=\"https://example.com/ct-report\""
</IfModule>
Note: The
Expect-CT header helps detect misissued certificates by requiring that all certificates presented are logged to a Certificate Transparency log.
10. Configuring Cross-Origin Headers
| Header | Values | Description |
|---|---|---|
| Cross-Origin-Embedder-Policy | require-corp, unsafe-none |
Controls embedding of cross-origin resources. |
| Cross-Origin-Opener-Policy | same-origin, same-origin-allow-popups, unsafe-none |
Controls whether a document can be opened in a cross-origin context. |
| Cross-Origin-Resource-Policy | same-origin, cross-origin, same-site |
Controls which origins can fetch resources. |
Example: Setting Cross-Origin Headers in Apache
<IfModule mod_headers.c>
Header set Cross-Origin-Embedder-Policy "require-corp"
Header set Cross-Origin-Opener-Policy "same-origin"
Header set Cross-Origin-Resource-Policy "same-origin"
</IfModule>
11. Setting Access-Control-Allow-Origin
| Directive | Values | Description |
|---|---|---|
| Header set Access-Control-Allow-Origin | * or https://example.com |
Controls which origins are allowed to access resources |
Example: Allow all origins
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
Example: Allow specific origin
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "https://example.com"
</IfModule>
Note: Using
* allows any origin, which can be a security risk. Prefer specific origins where possible.
12. Testing Security Headers
| Header | Description | Testing Command |
|---|---|---|
| Content-Security-Policy | Prevents cross-site scripting and other code injection attacks | curl -H "Content-Security-Policy: default-src 'self'" https://example.com |
| X-Content-Type-Options | Prevents MIME type sniffing | curl -H "X-Content-Type-Options: nosniff" https://example.com |
| X-Frame-Options | Prevents clickjacking attacks | curl -H "X-Frame-Options: DENY" https://example.com |
| X-XSS-Protection | Enables XSS filtering in browsers | curl -H "X-XSS-Protection: 1; mode=block" https://example.com |
Note: Use tools like SecurityHeaders.com or SSL Labs for comprehensive header analysis.