CSP(Content-Security-Policy)

shellder 发布于 2025-10-27 88 次阅读


同样是秋招的第一场web安全工程师的面试,面试官对CSP的深挖给我整个人问懵了,只能无意识的胡言乱语,这里同样是进行一下CSP的总结和输出吧,希望我能找到一份好的工作。

首先什么是CSP呢?CSP即content-security-policy,是一种web安全机制,用以防止XSS攻击和数据注入攻击,点击劫持(Clickjacking),以及确保网页通过https进行加载。它的核心思想是网站自己声明哪些外部资源是可信的,浏览器则根据这个策略来判断是否加载和执行这些资源。那它如何防御这些攻击呢?

XSS攻击的本质是攻击者通过注入恶意的<script>和事件属性如onerror,从而使得浏览器执行注入的JavaScript代码,从而实现劫持会话,窃取cookie,Hook DOM,加载远程恶意脚本。
首先,CSP对JavaScript脚本的来源进行了限制,script-src指令制定了可以从哪些域名加载JavaScript代码,如果攻击者注入的JavaScript代码不在白名单中,浏览器则会进行直接的拦截。如:
Content-Security-Policy: script-src 'self' https://cdn.example.com
这意味着只有当前域和cdn域的脚本可以被执行。


其次,CSP会禁止内联脚本的执行,如常见的xss攻击payload:<script>alert('test')</script>这种inline脚本,如果站点没有开启unsafe-inline,则任何内联脚本都无法执行。好,这里要强调一个概念,也就是什么是内敛脚本呢?内联脚本指的是直接写在HTML文档中的JavaScript代码,而非从其外部JS文件进行加载的,无论是直接注入 <script>,还是注入一段被拼接后执行的 JS,本质上都属于 CSP 所说的 “内联脚本”风险,因为它没有通过外部受信任的 JS 文件加载,而是直接存在于页面源代码中。这里有一个容易弄错的点,如CSP设置为script-src 'self',它允许的是来自本地域的js文件,而不允许内联脚本。即允许:<script src="/static/app.js"></script>但是不允许<script>console.log("内联脚本")</script>。那如何在有设置CSP的情况下使用自己的内敛脚本?

第一种方法是使用nonce。服务器会在生成页面前随机生成一个nonce,nonce是动态的,服务器应该对每个响应和请求生成新的nonce。服务器会在http响应头中将nonce写入CSP,并在html响应中把nonce写入到允许的内联脚本里,而浏览器收到响应后会解析header中的nonce值,检查内联脚本的nonce属性是否域允许的相同,如果相同则允许nonce执行。而由于nonce存在于http流量包中,容易受到中间人攻击,故nonce的传输需要https协议进行加密传输。

DOM型XSS注入和nonce。首先xss攻击分为三种类型,反射型xss,存储型xss,以及DOM型xss,其中危害最大的是存储型xss,而DOM型xss是不需要服务器响应的,故此有个问题,由于nonce是由服务器进行更新和发放的,那是不是nonce的使用无法阻止DOM型xss?答案为是的,nonce无法阻止DOM型xss。DOM型xss本质上是攻击者通过控制某个可被 JS 读取的来源(URL fragment、query、postMessage、localStorage 等),让页面上的已有脚本把这些不可信的字符串当成 HTML/JS 处理,从而执行恶意代码。nonce的使用本质上是设置允许的脚本来源而非数据被写入DOM。而CSP中禁止unsafe-eval来阻止eval() / new Function() / setTimeout(string):这些 API 把字符串当 JS来执行。(啊啊啊啊啊,这块我也很懵,等我彻底搞清楚了再来更新)

第二种方法则是使用hash(sha256),这种方法适合内联脚本不变的情况,这种方法需要对内联脚本进行hash值的计算,并将hash值写入到CSP中。但是如果内联脚本发生改变,则需要重新计算hash值。

CSP可以用来防护点击劫持,首先什么是点击劫持(Clickjacking)?点击劫持是指攻击者会搭建一个网站,并在网站上通过<iframe>嵌套用户的页面,然后把用户的页面用透明度或者样式遮盖在一个诱导按钮上,用户以为点的是攻击者网页的内容,其实点到的是用户网站上的敏感操作按钮。这可能会导致用户在不知情的情况下完成敏感操作(如转账、修改信息),以及用户信息泄露,授权误用等情况的发生。
而CSP中的frame-ancestors指令是专门用来防止点击劫持的,它会控制允许哪些域名可以将网站嵌套到<iframe>,<frame>,<object>中,例如Content-Security-Policy: frame-ancestors 'none';这意味着不允许任何网站通过 iframe 或 frame 嵌入当前页面。

CSP强制升级为https:一些网站会以https提供主文档,但通过 HTTP 提供其资源,从而形成混合内容,这样会造成http资源容易遭受中间人攻击以及https的加密性和完整性保护被削弱。CSP可以使用upgrade-insecure-requests将所有的http请求通通升级为https,但是有一种情况不会升级如跨域链接,即不会帮你将外部网站改为https。
和HSTS的区别:首先upgrade-insecure-requests位于CSP响应头,而HSTS位于strict-transfer-security响应头。再者,upgrade-insecure-requests是将当前页面内的资源和同源导航强制升 HTTPS,而HSTS则是浏览器以后访问这个域名,一律强制升 HTTPS

script-src:控制JavaScript脚本的加载来源。常见的限制内容有:允许哪些域可以加载脚本(self代表本站);是否允许inline script(‘unsafe-inline’);是否允许eval()(’unsafe-eval‘);是否使用nonce和hash来精准放行部分脚本。

style-src:控制CSS样式的加载来源。常见的限制有:是否允许外联样式(如来自 Google Fonts);是否允许内联样式(‘unsafe-inline’);是否允许使用style属性等。

img-src:控制图片的加载来源。常见的限制有:是否允许data URL嵌入图片。

default-src:默认资源加载策略(当其他指令未定义时使用)。假如default-src被赋予单一源表达式 'self'img-src被赋予两个源表达式:'self' 和 example.com,这意味图像必须与文档同源,或者从 example.com 加载,而所有其他资源必须与文档同源。
font-src:限制字体文件来源。
connect-src:限制 fetch / XHR / WebSocket 的请求来源。
frame-src/child-src:限制 iframe、frame 的加载来源。
media-src:限制音视频资源来源。
object-src:限制 Flash、PDF 等插件资源。
frame-ancestors:限制哪些域可以嵌入当前页面(防 clickjacking)。
report-url/report-to:CSP 报警上报地址。

CSP测试:在CSP部署前,可以仅对CSP设置进行测试,违反CSP要求的请求不会被拦截,但是会被记录,这可以通过Report-Only-Mode来实现:Content-Security-Policy-Report-Only: default-src 'self'这种情况下浏览器不会阻止资源的加载,而是会发送违规报告到定义的端点。如果Content-Security-Policy和Content-Security-Policy-Report-Only同时存在,这回都生效,违反Content-Security-Policy的资源加载会被阻止,而违反Content-Security-Policy-Report-Only的资源加载则会被记录。

其中关于违规报告的发送,有两种方法:第一种为:Reporting-Endpoints + report-to(现代标准);第二种为:report-uri(用以兼容一些旧的浏览器)
第一种方法首先要定义报告端点:
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"其中csp-endpoint为自己定义的名字,“https://example.com/csp-reports”则为服务器接收CSP报告的接口地址。之后要在策略中进行引用,这种请况下如果发送CSP 违规时,浏览器会把一份 JSON 格式的报告POST到
https://example.com/csp-reportsContent-Typeapplication/reports+json
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint
第二种方法则是如下:
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint; report-uri https://example.com/csp-reports

内容就先这样....DOM型XSS攻击的内容等我研究透了再更新吧!

此作者没有提供个人介绍。
最后更新于 2025-10-29