免费监控
logo prod

资讯与帮助

内容安全策略(CSP)入门:如何配置CSP来抵御XSS攻击

时间:2025-09-29
编辑:tance.cc

《什么是CSP(内容安全策略)?给你的网站内容加上一道“白名单”》

2.jpg

好了,安全架构师,欢迎来到我们的“最高安全级别”会议室。

我们之前配置的所有安全头,都像是在修补已知的漏洞。但网络世界里,最危险的,永远是未知的漏洞。特别是那种最常见、也最阴险的“跨站脚本攻击”(Cross-Site Scripting, XSS)。

XSS攻击,到底有多可怕?

  • 比喻: 让我们回到“大楼安保”的例子。XSS攻击,不像一个从外部撬锁的“小偷”。它更像一个混入你内部的“商业间谍”。这个间谍,伪装成一段看起来无害的“普通留言”,通过你网站的评论区,成功地进入了你的“大楼”内部(你的数据库)。

当下一位普通访客来浏览这条留言时,你的服务器会“忠实地”把这条包含恶意代码的留言,展示给这位访客。访客的浏览器,出于对你网站的绝对信任,会毫无防备地执行这段恶意代码。

  • 后果: 这段代码,现在是在你用户的浏览器里、顶着你网站的名义运行的。它可以:

    • 偷走用户的“身份证”(窃取用户的Cookie,从而冒充用户登录)。

    • 在你网站上“画牛皮癣”(篡改页面内容,插入广告或钓鱼链接)。

    • 把用户“骗走”(将用户重定向到恶意网站)。

你可能会想,我把程序写得天衣无缝,不就行了吗?但人非圣贤,孰能无过。即便是谷歌、Facebook,也无法保证自己的网站100%没有XSS漏洞。

我们需要一种釜底抽薪的防御机制。我们需要一种方法,即便“间谍”已经混进了大楼,我们也能让他无计可施

这种机制,就是内容安全策略(CSP)


CSP的核心思想:“白名单”制度


CSP的哲学,与我们之前讨论的所有“黑名单”都不同。它的核心思想是:

“与其费尽心机去记下所有‘坏人’的名单,不如直接制定一份‘好人’的白名单。凡是不在这份名单上的,无论他看起来多无辜,一律视为‘坏人’!”

CSP通过一个HTTP响应头,向用户的浏览器,下发一份极其严格的“可信资源白名单”。这份“白名单”,详细规定了,在你的网站上,浏览器被授权从哪些来源,加载哪些类型的资源。

  • 比喻: 你作为大楼的“最高安全主管”,给前台的“保安队长”(浏览器)下发了一份强制执行的《访客与供应商白• 名单》。这份名单上写着:

    • “所有工作人员(脚本),必须佩戴我们公司自己('self')的工牌。”

    • “所有装修材料(样式),只能从我们自己,以及‘红星美凯龙’(fonts.googleapis.com)这两家供应商采购。”

    • “所有午餐外卖(图片),只能从我们自己,以及‘山德士上校’(img.my-cdn.com)那里订购。”

    • “……任何未在此名单上的人或物,即便他持有看似合法的‘通行证’(即便代码是你服务器发出的),也一律禁止入内,并立刻向我汇报!”

当那个被注入到评论区的恶意脚本,试图在用户浏览器里运行时,浏览器这位“保安队长”,会立刻核对他的“白名单”,然后发现:“抱歉,http://hacker-site.com/evil.js 这个脚本供应商,不在我们今天的白名单上。禁止执行!

攻击,在发生前的最后一刻,被浏览器自己,就地正法了。



“白名单”的写法:CSP指令入门


CSP策略,就是由一长串的“指令(Directives)”组成的。每一条指令,都负责管理一类资源的“白名单”,指令之间用分号;隔开。

1. default-src:最基础的“默认规则”

  • 比喻: 这是你白名单的第一条,也是最重要的一条:“默认情况下,禁止所有人和所有供应商进入,除非我下面有特别许可。

  • 技术现实: default-src为所有其他没有明确指定的资源类型,设定了一个默认的加载策略。

  • 最佳实践: 一个最安全的起点,是default-src 'self';

    • 'self'是一个特殊的关键字,代表“只信任我自己当前的域名”。这条规则的意思是:“默认只允许加载来自我网站本身域名的资源。”

2. script-src:“脚本”的专属白名单

  • 比喻: 这是白名单里,关于“软件工程师”和“IT顾问”的准入规则。

  • 技术现实: 这是最重要的CSP指令,没有之一!因为它直接掌管着JavaScript的执行权限,是抵御XSS攻击的核心。

  • 示例: script-src 'self' https://www.google-analytics.com;

  • 解读: “本网站的脚本,只允许从我自己的域名,以及www.google-analytics.com(谷歌分析的官方脚本来源)这两个地方加载。其他任何来源的脚本,一律禁止!”

3. style-src:“样式”的专属白名单

  • 比喻: 这是关于“室内设计师”和“装修队”的准入规则。

  • 技术现实: 它规定了CSS样式表可以从哪里加载。

  • 示例: style-src 'self' https://fonts.googleapis.com 'unsafe-inline';

  • 解读:

    • 允许加载来自我自己域名fonts.googleapis.com(谷歌字体的官方样式来源)的CSS文件。

    • 'unsafe-inline'是一个“特例豁免”。它表示:“我允许在HTML里,直接使用<style>...</style>标签和style="..."属性。” 这是一个为了兼容老旧代码而存在的选项,但会降低安全性,应尽量避免。

4. img-src:“图片”的专属白名单

  • 比喻: 这是关于“摄影师”和“图片供应商”的准入规则。

  • 技术现实: 它规定了图片可以从哪里加载。

  • 示例: img-src 'self' data: https://img.my-cdn.com;

  • 解读: “本网站的图片,只允许来自我自己的域名Base64编码的data:格式,以及我自己的CDN域名img.my-cdn.com。”

其他常用指令还包括:

  • font-src 字体文件的白名单。

  • connect-src 你的脚本被允许连接(比如发起API请求)的域名白名单。

  • frame-src 允许嵌入到<iframe>里的域名白名单。



“静默观察”模式:只报告,不拦截


看到这里,你可能会有一个担忧:“这套白名单规则这么严格,万一我不小心,把我们自己的一个正常脚本给忘了加进去,那不是会导致网站功能直接瘫痪吗?”

问得好!所以,CSP为你提供了一种极其人性化的“试运行”模式。

  • 比喻: 在正式执行这套严格的“访客白名单”之前,你先把它交给“保安队长”,并告诉他:“你先按这个名单,观察一周。如果发现有不在名单上的人试图进入,你先不要拦他,让他进来。但你必须立刻、悄悄地,向我的办公室,提交一份关于这次‘违规闯入’的详细报告。”

  • 技术现实: 你可以通过发送一个名为 Content-Security-Policy-Report-Only 的响应头,来启用这个“只报告模式”。

    • 这个头后面的规则写法,和正式的CSP完全一样。

    • 但它不会真的去拦截任何资源的加载。

    • 取而代之的,是当它发现任何“违规”行为时,就会向你指定的report-urireport-to地址,发送一份JSON格式的违规报告

通过分析这些报告,你就能在不影响线上用户的情况下,完美地调整和补充你的白名单规则。直到报告里再也没有“误报”时,你就可以自信地,将Report-Only头,切换为正式的Content-Security-Policy头,让你的“白名单”正式上岗执法。



一份给普通网站的“CSP快速入门模板”


下面这份,是一份适用于绝大多数普通企业官网或博客的、相对安全、也相对宽松的CSP“快速入门”配置。你可以把它作为你制定自己策略的起点。

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.google-analytics.com; style-src 'self' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:;

这份“白名单”翻译过来就是:

  • 默认只相信我自己。

  • 脚本,额外信任谷歌分析。

  • 样式,额外信任谷歌字体。

  • 字体,额外信任谷歌字体的内容分发网络。

  • 图片,额外信任data:格式。

好了,安全架构师。现在,你已经掌握了这件网页安全领域里,最强大、最主动的“终极防御武器”。你学会了如何为你的网站,建立一套“默认拒绝、按需授权”的“白名单”体系。


客服
意见反馈