DASCTF X CBCTF 2022九月挑战赛
有所收获
dino3d
前端js小游戏,像是google小恐龙的3D版
抓包可以发现后端会有个check.php
检测
后端看不到逻辑,就先审审前端js的代码,f12抓包可以发现是由bulid.min.js
发起的
我们跟一下,再搜索找到了sn
函数,请求体的逻辑也在这
下个断点调试一下,可以发现checkCode的值
并且,我们还可以知道调用sn
的函数
直接控制台传值
Text Reverser
浅搜一下,发现是外国的一道原题改编的
https://pankas.top/2022/07/25/dicectf-hope-web%E9%83%A8%E5%88%86%E9%A2%98%E8%A7%A3/
这道题多了过滤手段,但不多,简单fuzz一下,发现双{ {
不可以,网上搜一下可以用{ % + print
绕过
payload = '''{%print(''.__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("nl /flag").read()'))%}'''[::-1] |
读文件过滤了cat
我直接用nl
读了
cbshop
也是国外的一道题改编过来的,nodejs的题,不得不说,老外真喜欢js啊
https://nanimokangaeteinai.hateblo.jp/entry/2022/08/09/022238#Web-209-simplewaf-28-solves
https://viblo.asia/p/corctf-2022-writeup-part-1-m68Z0Joj5kG
这里感叹一下,google真好用
给了源码
const fs = require('fs'); |
给了用户名和密码,但是在后面又会发现把密码截断了,并且是个emoji,我们得编码再传,这里直接在控制台操作
有9999这么多钱,我们发现依然买不了flag,继续往下看
... |
可以看到这个if里多了个token判断,但是我们向前找发现user
并没有这个属性,当然他不可能凭空存在,我们可以想到,js会向上去找他原型链寻找这个参数,注意看这里
Object.assign(order[user.username], product); |
这个username
可以改,我们可控,而这个assing
又是一个合并的操作,存在原型链污染,我们使username=__proto__
,将product
合并到order
原型上,order
和user
原型又都是Object
。这样我们就可以构造出token参数
然后我们发现,这里过滤掉了flag关键字,并提示去看readFileSync
这个函数,但是不影响我们读其他文件,如下
这里我们跟着分析一下readFileSync
https://github.com/nodejs/node/blob/main/lib/fs.js#L452
function readFileSync(path, options) { |
下面是读文件的操作,我们主要跟进openSync
function openSync(path, flags, mode) { |
这里有个getValidatedPath
似乎是获取文件路径,继续跟
function getValidatedPath (fileURLOrPath) { |
需要fileURLOrPath & href & origin
都不为空,接着看fileURLOrPath
function fileURLToPath(path) { |
function isURLInstance(fileURLOrPath) { |
这里需要path.protocol == 'file:'
,才能走到return,这里在isURLInstance
也能发现那三个值不能为null,因为是linux的环境,跟后面一个
function getPathFromURLPosix(url) { |
首先要url.hostname == ''
绕过if,这里可以发现它对传入的pathname进行了URL解码的操作,刚好看文档我们知道fs.readFileSync
是接受URL参数的
所以我们可以将flag进行编码绕过if检查,并且不影响读文件操作
并且要满足之前说到的几个参数条件
pathname
urlencodefile.origin
existsfile.href
existsfile.protocol = 'file:'
file.hostname = ''
DASCTF X CBCTF 2022九月挑战赛