逼逼叨
很难受啊,出去跑项目封闭管理,结果没打上,只能赛后复现了。
上班是真滴累
Web
[LitCTF 2025]多重宇宙日记
进来先随便注册个账户,说实话看到这样的题目第一眼怀疑二次注入、直接不想做
登陆后发现可以设置主题语言之类的,随便试试无果
查看页面源码
摘出JS中的关键代码,简单看下
其实第二处的注释已经给了很明确的暗示,修改isAdmin状态后自动刷新,再看第三处仅用JSON.parse()去进行数据处理,很简单的原型链污染,注意要放在settings键下:
{
"settings":{"theme": "123","language": "123","__proto__":{"isAdmin": true}
}
}
提交数据之后出现管理员面板,flag出现
这里多逼逼叨一句原型链污染
原型链污染
举个例子哈,假设咱最开始有这样的代码:
let user1 = {};
let user2 = {};console.log(user1.isAdmin); // undefined
console.log(user2.isAdmin); // undefined
这个时候咱想输出user1和user2的isAdmin属性返回undefined,因为压根没人设置过user1和user2的isAdmin属性。
那原型链之所以叫做原型链,它是条链子,也就是说,当JS在当前的user1和user2中找不到这个属性的时候,它会去追根溯源:好,你这个Object没有,那我去找你的原型,也就是Object.prototype的isAdmin
那这个proto是哪来的,凭什么user1、user2会有这个玩意?
这个prototype被叫做对象的原型,说白了,也就是我创建use1、user2时候自动生成的隐藏属性,好比你人刚生下来,父母给你起名字叫小白,那你是否全身上下只有一个特征,是否你除了你叫小白以外就没有任何信息了?肯定不是啊,几斤几两?男孩女孩?好不好玩?等等等等,对吧~
对应来说JS对象的隐藏属性就是这些
方法名 | 说明 |
---|---|
toString() | 返回 [object Object],或者经过重写的内容 |
hasOwnProperty() | 判断属性是不是对象自身拥有 |
valueOf() | 对象的原始值表示(比如自动类型转换时) |
isPrototypeOf() | 判断是否在原型链上 |
propertyIsEnumerable() | 属性是否可枚举 |
toLocaleString() | 本地化版本的 toString() |
constructor | 指向构造函数,例如 Object 本身 |
但这里并没有我们所需的内容,这个时候我们就可以给Object.prototype去进行污染,就类似于示例中的Object.prototype.isAdmin = true这样去赋值
Object.prototype.isAdmin = true;console.log(user1.isAdmin); // true
console.log(user2.isAdmin); // true
常见防御手法
const dangerousKeys = ['__proto__', 'prototype', 'constructor'];function sanitize(obj) {for (let key of dangerousKeys) {if (key in obj) {delete obj[key];}}
}
绕过方法:
{"settings": {"\u005f_proto\u005f": {"isAdmin": true}}
}
[LitCTF 2025]nest_js
这题挺无语的,admin/password秒了
看一眼网站组件
Next.js,一猜考的今年的day
x-middleware-subrequest:
middleware:middleware:middleware:middleware:middleware
/dashboard
[LitCTF 2025]星愿信箱
fenjin秒了