Content Security Policy 实战:用 CSP 降低 XSS 风险

XSS(跨站脚本攻击)长期占据 OWASP Top 10 的显著位置,而 Content Security Policy(CSP)是浏览器层面抵御 XSS 最有力的防线之一。本文将结合 XSS 的常见攻击方式与前端防御思路,深入讲解 CSP 的实战配置,并延伸讨论 SQL 注入防护与 Linux 服务器安全加固,帮助开发者构建纵深防御体系。

一、XSS 的常见方式与前端防御

XSS 的本质是攻击者将恶意脚本注入到页面中,使浏览器在受害者的上下文中执行。常见类型包括:

  • 存储型 XSS:恶意脚本被持久化到数据库(如评论区),所有访问该页面的用户都会中招。
  • 反射型 XSS:恶意脚本通过 URL 参数传入,服务器将其直接回显到页面中。
  • DOM 型 XSS:前端 JavaScript 直接将不可信数据写入 DOM,如 innerHTMLdocument.write

前端防御的核心原则是 “永不信任用户输入”

  1. 输出编码:根据输出位置(HTML、属性、JS、URL)进行对应编码。
  2. 使用安全的 DOM API:优先使用 textContent 而非 innerHTML,使用 setAttribute 而非字符串拼接。
  3. 输入验证与白名单:对 URL、富文本等做严格过滤。
  4. CSP:即便前几层被绕过,CSP 也能限制脚本执行来源,成为最后一道防线。

二、CSP 是什么

CSP 通过 HTTP 响应头 Content-Security-Policy 告诉浏览器:哪些资源可以加载、哪些脚本可以执行。它本质上是一份白名单策略。

一个基础的 CSP 头如下:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none';

关键指令说明:

  • default-src 'self':默认只允许同源资源。
  • script-src:限制脚本来源,禁止内联脚本(不写 'unsafe-inline')。
  • object-src 'none':禁用 Flash 等插件,防止绕过。
  • base-uri 'self':防止 <base> 标签劫持相对路径。
  • frame-ancestors 'none':防止点击劫持。

三、CSP 实战配置策略

1. 从 Report-Only 开始

直接上线严格 CSP 可能导致页面崩溃。建议先用 Content-Security-Policy-Report-Only 观察违规:

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

收集一段时间报告后,再逐步收紧策略。

2. 消除内联脚本

CSP 最大的痛点是内联脚本。解决方案:

  • <script> 内容外移到 .js 文件。
  • 对必须内联的脚本使用 nonce
<script nonce="random-value">
  // 内联脚本
</script>

响应头中:

script-src 'nonce-random-value' 'strict-dynamic';

'strict-dynamic' 允许被信任脚本动态加载的子脚本,现代浏览器推荐使用。

3. 避免 unsafe-inline 与 unsafe-eval

'unsafe-inline' 会让 CSP 形同虚设。若确实需要内联样式,可用 style-src 'self' 'unsafe-inline' 但应尽量避免。eval()new Function() 等动态执行也应禁用。

4. 结合后端模板

在服务端渲染时,为每个请求生成随机 nonce,并注入到模板中。例如 Node.js + Express:

app.use((req, res, next) => {
  res.locals.nonce = crypto.randomBytes(16).toString('base64');
  res.setHeader(
    'Content-Security-Policy',
    `script-src 'nonce-${res.locals.nonce}' 'strict-dynamic'`
  );
  next();
});

四、CSP 不是银弹

CSP 能大幅降低 XSS 风险,但无法覆盖所有场景:

  • 老版本浏览器兼容性有限。
  • 配置不当(如通配符 *)会留下漏洞。
  • 无法防御服务端漏洞导致的敏感数据泄露。

因此,CSP 必须与其他防御手段配合使用。

五、延伸:MySQL 防止 SQL 注入的几种写法

SQL 注入与 XSS 同属注入类漏洞,防御核心是 参数化查询

  1. 预处理语句(推荐)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
  1. 使用 ORM:如 Laravel Eloquent、Hibernate,自动转义参数。
  2. 最小权限原则:数据库账号仅授予必要权限。
  3. 输入验证:对类型、长度、格式做校验,但不可替代参数化。

切忌字符串拼接 SQL,也不要依赖 addslashes 等手工转义。

六、Linux 服务器安全加固清单

服务器是应用的最后一道屏障,建议定期检查:

  • 更新补丁apt update && apt upgradeyum update
  • SSH 加固:禁用 root 登录、改用密钥认证、修改默认端口、使用 fail2ban
  • 防火墙:仅开放必要端口,使用 ufwiptables
  • 最小化服务:卸载无用软件,关闭不必要端口。
  • 日志审计:启用 auditd,集中收集日志。
  • 文件权限:敏感文件设置 600,目录 750
  • 定期备份:离线备份并验证可恢复性。

七、总结

CSP 是抵御 XSS 的重要武器,但它的价值在于 纵深防御 中的一环。前端做好输出编码与安全 DOM 操作,后端使用参数化查询防止 SQL 注入,服务器层面持续加固,三者结合才能构建真正健壮的 Web 安全体系。从今天开始,为你的站点加上 CSP 报告头,迈出安全加固的第一步。

未经允许不得转载:任鹏个人博客 » Content Security Policy 实战:用 CSP 降低 XSS 风险

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏