阿里云主机折上折
  • 微信号
Current Site:Index > Security headers (such as 'X-Frame-Options', 'X-XSS-Protection', etc.)

Security headers (such as 'X-Frame-Options', 'X-XSS-Protection', etc.)

Author:Chuan Chen 阅读数:12341人阅读 分类: HTML

Overview of Security Headers

Security headers are part of HTTP response headers used to control browser behavior and enhance web application security. They effectively defend against common attacks such as clickjacking, XSS, and MIME type confusion. In modern web development, properly configuring security headers has become a fundamental security practice.

X-Frame-Options

X-Frame-Options controls whether a page can be embedded in <frame>, <iframe>, or <object>, primarily defending against clickjacking attacks. It has three possible values:

  • DENY: Completely prohibits embedding
  • SAMEORIGIN: Allows embedding only by same-origin pages
  • ALLOW-FROM uri: Allows embedding from a specified source (deprecated)
# Nginx configuration example
add_header X-Frame-Options "SAMEORIGIN";
// Express middleware example
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  next();
});

Real-world example: Banking websites often use DENY to prevent malicious sites from embedding their login pages in iframes for phishing attacks.

X-XSS-Protection

X-XSS-Protection controls the browser's built-in XSS filter. Although modern browsers are gradually phasing out this header, it still holds value in older browsers:

  • 0: Disables filtering
  • 1: Enables filtering
  • 1; mode=block: Enables filtering and blocks rendering
  • 1; report=<uri>: Enables filtering and reports (Chrome only)
# Apache configuration
Header set X-XSS-Protection "1; mode=block"

Note: Modern applications should primarily rely on Content Security Policy (CSP) for XSS defense, with this header serving as a supplement.

Content-Security-Policy

CSP is one of the most powerful security headers, using a whitelist mechanism to control resource loading:

Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.example.com; style-src 'self' 'unsafe-inline'; img-src *; media-src media.example.com; child-src 'none'

Key directives include:

  • default-src: Default resource loading policy
  • script-src: Controls JavaScript execution
  • style-src: Controls CSS loading
  • connect-src: Restricts connections like XMLHttpRequest
  • report-uri: Violation reporting address
<!-- Example: Only allows loading same-origin resources -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

Advanced usage: Nonces or hashes can allow specific inline scripts:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Only scripts with matching nonces will execute
</script>

Strict-Transport-Security

HSTS forces browsers to use HTTPS connections:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age: Validity period (seconds)
  • includeSubDomains: Includes all subdomains
  • preload: Requests inclusion in browser preload lists
// Node.js implementation
app.use((req, res, next) => {
  if(req.secure) {
    res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  }
  next();
});

X-Content-Type-Options

The nosniff option prevents browser MIME type sniffing:

X-Content-Type-Options: nosniff

This prevents browsers from executing non-JavaScript files as JS, defending against MIME type confusion attacks.

# Enable for all static resources
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
  add_header X-Content-Type-Options nosniff;
}

Referrer-Policy

Controls Referer header information leakage:

Referrer-Policy: strict-origin-when-cross-origin

Common values:

  • no-referrer: Completely disables
  • same-origin: Sends only for same-origin requests
  • strict-origin: Sends only the origin (excluding path)
  • strict-origin-when-cross-origin: Sends only the origin for cross-origin requests
<!-- Set via meta tag -->
<meta name="referrer" content="strict-origin-when-cross-origin">

Feature-Policy/Permissions-Policy

Controls browser feature access permissions (renamed to Permissions-Policy in newer versions):

Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=()
// Disable unnecessary features
app.use((req, res, next) => {
  res.setHeader('Permissions-Policy', 'accelerometer=(), camera=(), geolocation=()');
  next();
});

Security Header Best Practices

  1. Combination: Single headers cannot provide comprehensive protection. A typical combination:

    add_header X-Frame-Options "DENY";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";
    add_header Content-Security-Policy "default-src 'self'";
    add_header Referrer-Policy "strict-origin-when-cross-origin";
    
  2. Testing: Use security header scanning tools to verify configurations:

    curl -I https://example.com | grep -iE '(xss|frame|csp)'
    
  3. Gradual Deployment: CSP can first use report-only mode:

    Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
    
  4. Performance Considerations: Excessive security headers increase HTTP header size; balance security and performance.

Common Issues and Solutions

CSP blocking third-party resources:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com

HSTS causing development environment issues:

  • Avoid long max-age in local development
  • Clear HSTS settings via browser

iframe integration conflicts with X-Frame-Options:

Content-Security-Policy: frame-ancestors https://partner.example.com

CSP and nonce management: Build tools can automatically generate nonces:

// Webpack plugin example
const crypto = require('crypto');
const HtmlWebpackPlugin = require('html-webpack-plugin');

class NoncePlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('NoncePlugin', (compilation) => {
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'NoncePlugin',
        (data, cb) => {
          const nonce = crypto.randomBytes(16).toString('base64');
          data.html = data.html.replace(/<script/g, `<script nonce="${nonce}"`);
          cb(null, data);
        }
      );
    });
  }
}

Modern Browser Security Evolution

As browser security models evolve, some header behaviors have changed:

  1. CSP Level 3: New directives like worker-src, prefetch-src
  2. Reporting API: Unified violation reporting mechanism
    Reporting-Endpoints: default="https://example.com/reports"
    Content-Security-Policy: default-src 'self'; report-to default
    
  3. Trusted Types: DOM XSS defense
    Content-Security-Policy: require-trusted-types-for 'script'
    

Server Configuration Examples

Complete Apache Configuration:

<IfModule mod_headers.c>
  Header set X-Frame-Options "DENY"
  Header set X-Content-Type-Options "nosniff"
  Header set X-XSS-Protection "1; mode=block"
  Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://*.example.com; font-src 'self'; connect-src 'self' https://api.example.com; frame-src 'none'; object-src 'none';"
  Header set Referrer-Policy "strict-origin-when-cross-origin"
  Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
  Header set Permissions-Policy "geolocation=(), camera=()"
</IfModule>

CloudFront Lambda@Edge:

exports.handler = (event, context, callback) => {
  const response = event.Records[0].cf.response;
  response.headers['x-frame-options'] = [{ key: 'X-Frame-Options', value: 'DENY' }];
  response.headers['content-security-policy'] = [{ 
    key: 'Content-Security-Policy', 
    value: "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; base-uri 'self'; form-action 'self'"
  }];
  callback(null, response);
};

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.