Published on

Understanding Security Headers

Authors
  • avatar
    Name
    Ankit
    Twitter

Security headers are HTTP response headers that help secure web applications by mitigating various vulnerabilities. Below is an in-depth explanation of key security headers, their parameters, and implementation.

1. X-XSS-Protection

Purpose:
Mitigates Cross-Site Scripting (XSS) attacks by stopping a page from loading if an XSS attack is detected.

Example Situation:
A user visits a vulnerable website that reflects their input directly in the HTML response. The attacker crafts a malicious URL with a <script> tag and tricks the user into clicking it. Without the X-XSS-Protection header, the browser executes the script, leading to an XSS attack. With X-XSS-Protection: 1; mode=block, the browser detects the malicious script and prevents the page from rendering.

Directives:

  • 0: Disables the XSS filter.
  • 1: Enables the XSS filter (default).
  • 1; mode=block: Enables the filter and prevents rendering of the page if an attack is detected.
  • 1; report=<reporting-URI>: Enables the filter, sanitizes the page, and sends a report to the specified URI.

Implementation:

For Apache: Header set X-XSS-Protection “1; mode=block”

For Nginx: add_header X-XSS-Protection “1; mode=block”;

Limitations:
Modern browsers now recommend using Content Security Policy (CSP) instead of relying on this header.


2. Content-Security-Policy (CSP)

Purpose:
Prevents XSS, clickjacking, and data injection attacks by specifying which resources (scripts, styles, images, etc.) can be loaded.

Example Situation:
Your website loads JavaScript from a trusted CDN. An attacker injects a malicious <script> tag pointing to their server. Without CSP, the browser executes the script. With Content-Security-Policy: script-src 'self' https://trusted.cdn.com, the browser blocks any scripts not from your domain or the trusted CDN.

Directives:

  • default-src: Specifies default resource sources.
  • script-src: Defines allowed sources for JavaScript.
  • style-src: Defines allowed sources for CSS.
  • frame-ancestors: Controls which origins can embed the page in frames.
  • report-uri: Specifies where violation reports should be sent.

Implementation:

For Apache: Header set Content-Security-Policy “default-src ‘self’; script-src ‘self’ https://trusted.cdn.com”

For Nginx: add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’;”;

Advantages:
CSP provides granular control over resource loading and is highly effective against XSS attacks.


Purpose:
Protects cookies from being accessed via JavaScript, mitigating cookie theft in XSS attacks.

Example Situation:
An attacker exploits an XSS vulnerability to steal session cookies via document.cookie. Without the HttpOnly flag, cookies are accessible to JavaScript and can be stolen. With Set-Cookie: sessionid=abc123; HttpOnly, the browser prevents JavaScript from accessing cookies, mitigating this risk.

Directive Example: Set-Cookie: sessionid=abc123; HttpOnly

Implementation Example in Node.js:

res.cookie(‘sessionid’, ‘abc123’, { httpOnly: true });

Advantages:
Prevents client-side scripts from accessing sensitive cookies.


Purpose:
Prevents cookies from being sent with cross-site requests to mitigate CSRF (Cross-Site Request Forgery) attacks.

Example Situation:
An attacker tricks a user into clicking a link that sends a cross-site request to your application, using their session cookie for authentication (CSRF attack).
With Set-Cookie: sessionid=abc123; SameSite=Strict, cookies are not sent with cross-site requests, blocking the CSRF attack.

Directives:

  • Strict: Cookies are sent only with requests originating from the same site.
  • Lax (default): Cookies are sent with top-level navigation but not with embedded content.
  • None: Cookies are sent with cross-site requests but must also have the Secure attribute.

Directive Example: Set-Cookie: sessionid=abc123; SameSite=Strict; Secure

Implementation Example in Node.js:

res.cookie(‘sessionid’, ‘abc123’, { sameSite: ‘Strict’, secure: true });


5. X-Frame-Options

Purpose:
Prevents clickjacking by controlling whether a webpage can be embedded in an iframe.

Example Situation:
An attacker embeds your website in an invisible iframe on their malicious site and overlays fake buttons to trick users into clicking (clickjacking).
With X-Frame-Options: DENY, browsers block your website from being embedded in iframes, preventing clickjacking.

Directives:

  • DENY: Prevents embedding in any frame.
  • SAMEORIGIN: Allows embedding only on the same origin.
  • ALLOW-FROM uri (deprecated): Allows embedding only from a specific origin.

Implementation Example in Apache/Nginx:

For Apache: Header set X-Frame-Options “SAMEORIGIN”

For Nginx: add_header X-Frame-Options “DENY”;


6. Cross-Origin Resource Sharing (CORS)

Purpose:
Controls how resources on a server can be accessed by scripts running on other origins to prevent unauthorized cross-origin requests.

Example Situation:
Your API is hosted on api.example.com, but your front-end runs on app.example.com. By default, browsers block cross-origin requests due to the Same-Origin Policy (SOP).
With Access-Control-Allow-Origin: https://app.example.com, you explicitly allow requests from your front-end domain.

Key Headers and Parameters:

  • Access-Control-Allow-Origin: Specifies allowed origins (* for all origins).
  • Access-Control-Allow-Credentials: Indicates whether credentials (cookies, HTTP authentication) are allowed.
  • Access-Control-Allow-Headers: Lists allowed custom headers.

Example Response Header: Access-Control-Allow-Origin: https://app.example.com Access-Control-Allow-Credentials: true


7. Same-Origin Policy (SOP)

Purpose:
While not an HTTP header itself, SOP is a browser-enforced security model that restricts how scripts interact with resources from different origins. It ensures that scripts can only access data from the same origin (protocol, domain, port).

Example Situation:
You visit malicious-site.com, which embeds an iframe of your bank's website (bank.com). Without SOP, JavaScript on malicious-site.com could access sensitive data in the iframe (e.g., account balance).
SOP ensures that scripts on malicious-site.com cannot access resources or DOM elements from bank.com.

Note: SOP is enforced by browsers and does not require a specific header.


8. X-Content-Type-Options

Purpose:
Prevents browsers from MIME-sniffing a response away from its declared content type to avoid attacks like MIME confusion.

Example Situation:
Your server serves an image file (image.jpg) with a declared MIME type of image/jpeg. An attacker uploads a malicious file disguised as an image but containing HTML/JavaScript. Without this header, browsers might "sniff" the content and execute it as code.
With X-Content-Type-Options: nosniff, browsers strictly interpret files based on their declared MIME type and prevent execution of malicious content.

Directive Example: X-Content-Type-Options: nosniff

Implementation Example in Apache/Nginx:

For Apache: Header set X-Content-Type-Options “nosniff”

For Nginx: add_header X-Content-Type-Options “nosniff”;


9. HTTP Strict Transport Security (HSTS)

Purpose:
Forces browsers to use HTTPS instead of HTTP, protecting against man-in-the-middle (MITM) attacks and cookie hijacking.

Example Situation:
Imagine a user types http://example.com into the browser. Without HSTS, the browser first connects via HTTP before redirecting to HTTPS, leaving a window for MITM attacks. With HSTS, the browser automatically uses HTTPS for all connections, even if the user types http://.

Directives:

  • max-age: Time (in seconds) the browser should remember to only use HTTPS.
  • includeSubDomains: Applies the rule to all subdomains.
  • preload: Requests inclusion in browser preload lists for HSTS.

Example Header: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Implementation in Apache/Nginx:

For Apache: Header always set Strict-Transport-Security “max-age=63072000; includeSubDomains; preload”

For Nginx: add_header Strict-Transport-Security “max-age=63072000; includeSubDomains; preload”;

Conclusion of Security Headers

Header/Attribute NamePurpose/Attack MitigatedEffectiveness/Scope of ProtectionEase of Implementation
X-XSS-ProtectionBasic protection against reflected XSSLimited; deprecated in favor of CSPEasy
Content-Security-PolicyPrevents XSS and resource injectionHighly effective but complex to configureModerate
HttpOnlyProtects cookies from JavaScript accessLimited to cookie theft preventionEasy
SameSiteMitigates CSRFEffective for cross-site cookie controlEasy
X-Frame OptionsPrevents clickjackingEffective but limited compared to CSP's frame directivesEasy
CORSControls cross-origin resource sharingEffective for API/resource access controlModerate
SOPRestricts cross-origin interactionsEnforced by browsers; foundational security modelAutomatic
X-Content-Type OptionsBlocks MIME sniffingEffective for preventing content-type-based attacksEasy
Strict-Transport-SecurityEnforces HTTPS by instructing browsers to only connect over HTTPSHighly effective for ensuring secure connections.Easy