阿里云主机折上折
  • 微信号
Current Site:Index > Use CSP (Content Security Policy) to prevent XSS

Use CSP (Content Security Policy) to prevent XSS

Author:Chuan Chen 阅读数:61948人阅读 分类: 前端安全

What is CSP

CSP (Content Security Policy) is a browser-implemented security mechanism designed to detect and mitigate certain types of attacks, including cross-site scripting (XSS) and data injection attacks. It works by defining the allowed sources for loading resources, restricting the browser to only execute or render resources from these sources. The core idea of CSP is a whitelist mechanism, where developers explicitly tell the browser which resources can be loaded, while all others are blocked.

How CSP Protects Against XSS

XSS attacks typically involve injecting malicious scripts into web pages for execution. CSP effectively prevents XSS in the following ways:

  1. Blocking Inline Script Execution: By default, CSP prevents inline code in <script> tags and javascript: pseudo-protocols.
  2. Restricting Script Sources: Only allows loading script files from specific domains.
  3. Blocking eval-like Functions: Disables dynamic code execution methods such as eval() and setTimeout(string).
  4. Restricting Non-Static Resources: Controls the loading sources for fonts, frames, images, and other resources.

Three Ways to Implement CSP

Via HTTP Headers

The most recommended method is to set it through HTTP response headers:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src *; media-src media1.com media2.com; report-uri /csp-violation-report-endpoint

Via Meta Tag

Useful when server configuration cannot be modified:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

Via Report-Only Mode

Monitors without enforcement, suitable for debugging:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-violation-report-endpoint

Detailed Explanation of CSP Directives

Common Directives

  • default-src: Default policy for directives not explicitly specified.
  • script-src: Controls JavaScript loading sources.
  • style-src: Controls CSS loading sources.
  • img-src: Controls image loading sources.
  • connect-src: Controls sources for XHR, WebSocket, etc.
  • font-src: Controls font file loading sources.
  • object-src: Controls tags like <object>, <embed>, and <applet>.
  • media-src: Controls media resources like <audio> and <video>.
  • frame-src: Controls <iframe> loading sources (deprecated, replaced by child-src).
  • child-src: Controls child contexts (e.g., iframe, worker).
  • worker-src: Controls worker, shared worker, and service worker sources.

Special Values

  • 'none': Blocks all resources.
  • 'self': Allows only same-origin resources.
  • 'unsafe-inline': Allows inline scripts/styles (reduces security).
  • 'unsafe-eval': Allows dynamic code execution (e.g., eval).
  • 'strict-dynamic': Trusts scripts dynamically loaded by already executed scripts.
  • 'nonce-<base64-value>': Allows specific inline scripts using a one-time random value.
  • 'sha256-<hash-value>': Allows specific inline scripts using a hash value.

Practical CSP Configuration Examples

Basic Security Configuration

Content-Security-Policy: 
  default-src 'none';
  script-src 'self' 'unsafe-inline' 'unsafe-eval';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  font-src 'self';
  connect-src 'self';
  form-action 'self';
  frame-ancestors 'none';
  base-uri 'self';
  report-uri /csp-report

Strict Configuration (Recommended)

Content-Security-Policy: 
  default-src 'none';
  script-src 'self' https://cdn.example.com;
  style-src 'self';
  img-src 'self' data: https://*.example-cdn.com;
  font-src 'self';
  connect-src 'self' https://api.example.com;
  form-action 'self';
  frame-ancestors 'none';
  base-uri 'self';
  report-uri /csp-report

Configuration Allowing Google Analytics

Content-Security-Policy: 
  default-src 'self';
  script-src 'self' https://www.google-analytics.com 'unsafe-inline';
  img-src 'self' https://www.google-analytics.com;
  style-src 'self' 'unsafe-inline';
  connect-src 'self' https://www.google-analytics.com;
  report-uri /csp-report

Handling Inline Scripts and Styles

Using Nonce

The server generates a random value and injects it into the CSP header and script tag:

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // This script will execute
</script>

<script>
  // This script will be blocked
</script>

Using Hash

Calculate the SHA hash of the script content and add it to CSP:

Content-Security-Policy: script-src 'sha256-abc123...'
<script>
  // The content must exactly match the hash calculation
  alert('Hello, world.');
</script>

CSP Reporting Mechanism

Violation Report Configuration

Content-Security-Policy: default-src 'self'; report-uri /csp-report-endpoint

Example Report (POST Data)

{
  "csp-report": {
    "document-uri": "https://example.com/page.html",
    "referrer": "https://example.com/",
    "violated-directive": "style-src 'self'",
    "effective-directive": "style-src",
    "original-policy": "default-src 'self'; style-src 'self'",
    "disposition": "enforce",
    "blocked-uri": "https://evil.com/malicious.css",
    "line-number": 10,
    "column-number": 20,
    "source-file": "https://example.com/page.html",
    "status-code": 200,
    "script-sample": ".evil { color: red; }"
  }
}

Common Issues and Solutions

Third-Party Integration Issues

Issue: CSP errors when using third-party libraries (e.g., jQuery, Bootstrap).

Solutions:

  1. Host the library on your own server and use 'self'.
  2. Add the CDN address to the whitelist:
    script-src 'self' https://code.jquery.com
    
  3. Use Subresource Integrity (SRI):
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"
            integrity="sha384-KyZXEAg3QhqLMpG8r+Knujsl5/1EN..."
            crossorigin="anonymous"></script>
    

Inline Event Handler Issues

Issue: HTML event handlers like onclick are blocked.

Solutions:

  1. Use external scripts to add event listeners:
    document.getElementById('myButton').addEventListener('click', function() {
      // Handle click
    });
    
  2. Use 'unsafe-inline' (not recommended).
  3. Use CSP Level 3's 'unsafe-hashes'.

Dynamic Style Issues

Issue: JavaScript dynamically modifying styles is blocked.

Solutions:

  1. Switch to class toggling instead of direct style modification:
    element.classList.add('active');
    
  2. Use 'unsafe-inline' or hashes/nonces.

CSP and Modern Frontend Frameworks

React App Configuration

React requires 'unsafe-inline' for its event system:

Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'unsafe-eval' 'unsafe-inline';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  connect-src 'self' https://api.example.com;

Vue App Configuration

Vue requires 'unsafe-eval' for template compilation:

Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'unsafe-eval';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;

Angular App Configuration

Angular requires 'unsafe-eval' for JIT compilation:

Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'unsafe-eval';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;

For AOT-compiled Angular apps, 'unsafe-eval' can be removed.

CSP Deployment Strategies

Phased Deployment

  1. Reporting Phase: Use Content-Security-Policy-Report-Only to monitor potential issues.
  2. Loose Policy: Initially allow necessary 'unsafe-inline' and 'unsafe-eval'.
  3. Strict Policy: Gradually remove unsafe options, replacing them with nonces/hashes.
  4. Continuous Optimization: Adjust policies based on reports.

Monitoring and Maintenance

  1. Set up a reporting endpoint to collect violation data.
  2. Regularly review CSP reports.
  3. Adjust CSP policies as the application evolves.
  4. Use automated tools to test CSP effectiveness.

Advanced CSP Techniques

Using strict-dynamic

Content-Security-Policy: script-src 'nonce-abc123' 'strict-dynamic'

Allows scripts dynamically loaded by trusted scripts to execute, suitable for modern modular applications.

Multiple CSP Policies

Multiple CSP headers can be combined, with policies enforcing cumulative restrictions:

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

The final policy is script-src 'self' https://cdn.example.com.

Preload Directives

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

Controls sources for <link rel="preload"> resources.

CSP Synergy with Other Security Mechanisms

Combined with Subresource Integrity (SRI)

<script src="https://example.com/script.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Combined with Feature Policy

Content-Security-Policy: default-src 'self'
Feature-Policy: geolocation 'none'; microphone 'none'

Combined with Expect-CT

Content-Security-Policy: default-src 'self'
Expect-CT: max-age=86400, enforce, report-uri="https://example.com/report"

Limitations of CSP

  1. Browser Compatibility: Varying levels of CSP support across browsers.
  2. Configuration Complexity: Strict CSP may require refactoring existing code.
  3. False Positives: Overly strict policies may block legitimate resources.
  4. Performance Impact: Complex policies may increase browser processing time.
  5. Not a Panacea: Does not protect against CSRF, SQL injection, or other attacks.

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

如果侵犯了你的权益请来信告知我们删除。邮箱: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 ☕.