原型链污染
javascript中,每个对象都有一个原型,指向另一个对象的引用,当我们访问一个对象的属性时,若对象没有这个属性,javascript引擎会在他的原型对象中查找这个属性,这个过程会一直持续,直到找到该属性或者到达原型链末尾
攻击者可利用这个特性,修改一个对象的原型链污染程序
例:
攻击者在一个对象的原型链设置一个恶意的属性或方法,当程序后续执行中访问该属性或方法时,会执行攻击者的恶意代码
_proto_和prototype
在javascript中,每个对象都有名为_proto_的内置属性,指向该对象的原型
同时,每个函数也都有名为prototype的属性,他是一个对象,包含构造函数的原型对象应具有的属性和方法
简单来说_proto_属性是指向该对象的原型
prototype属性是用于创建该对象的构造函数原型
举个例子,打开火狐浏览器,f12,切换控制台,写入代码
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person1 = new Person('Alice');
person1.greet(); // 输出 "Hello, my name is Alice"
在例子中,我们创建了一个名为Persion的函数,将prototype上的greet设置为一个打招呼的函数,当创建名为person1实例时,会继承person.prototype对象上的greet方法,因此调用person1.greet时,会输出"Hello, my name is Alice"
从这可看出prototype时person的一个属性,用类person进行实例化的对象,都会拥有prototype的全部内容
我们实例化出来的person1对象,不能通过prototype访问原型,通过_proto_就可以实现访问person原型
console.log(person1.__proto__ === Person.prototype); // 输出 true
总结:
prototype是一个类的属性,所有类对象在实例化的时候会拥有prototype中的属性和方法
一个对象_proto_属性,指向这个对象所在的类的prototype属性
具体过程
原链污染举例
对b进行b.proto.number=520操作后,即使c为空,设置的number属性仍为520,就达到原链污染目的
疑问一:为什么执行过b.__proto__.number=520后,输出b的值仍为1314
因为javascript执行存在一种机制,调用过程时如下所示
1.在b对象中寻找number
2.当b对象中没有找到时,会在b._proto_中寻找到number属性
3.如果未找到,此时会去b.__proto__.__proto__中寻找number属性
也就是说,它从自身开始寻找,然后一层一层向上递归寻找,直到找到或是递归到null
为止,此机制被称为JavaScript继承链,我们这里的污染的属性是在b.__proto__中,而我们的b对象本身就有number,所以其值并未改变。
疑问二:为什么新建的值为空的c对象,调用c.number竟然有值而且为我们设定的520
当明白上个问题时,这个问题也就迎刃而解了,我们这里的c对象虽然是空的,但JavaScript继承链的机制就会使它继续递归寻找,此时也就来到了c.__proto__中寻找number属性,我们刚刚进行了原型链污染,它的c.__proto__其实就是Object.protoype,而我们进行污染的b.__proto__也是Object.prototype,所以此时它调用的number就是我们刚刚污染的属性,所以这也就是为什么c .number=520
拓展
js大小写函数
对于toUpperCase()函数处理变成大写
对于toLowerCase()函数处理变成小写
例:[NewStarCTF 2023 公开赛道]OtenkiGirl
打开是个填写页面,concat与reason必须写,输入内容进行抓包
javascript数据格式提交,可以改用_proto_污染属性
查看附件源码,app.js引入路由文件,进入打开
info与submit文件
初始化一个mintimestamp变量,从配置对象获取min_public_time属性的值,如果不存在则使用默认配置对象DEFAULT_CONFIG中的min_public_time属性值,然后通过new Date()构造一个函数将该时间转换为一个日期对象,并使getTime()方法获取其对应的时间戳
追踪查看到config.js时发现没有该配置属性,所以会使用DEFAULT_CONFIG变量中的min_public_time属性
这里可以原型链污染min_public_time更早日期,尝试绕过这个日期限制
payload
{
"contact": "111",
"reason": "111",
"__proto__":{
"min_public_time": "2018-01-01"
}
}
污染成功
重新进入搜索flag
例子:攻防世界wife_wife
打开有登录界面与注册
对注册界面选择管理员抓包
题目是node.js后端服务器,js写的,进行原型链污染
payload
{
"username":"z","password":"x",
"__proto__":{
"isAdmin":true
}
}
再次使用创建账号登录得到正确flag
标签:proto,对象,number,污染,原型,prototype,属性 From: https://www.cnblogs.com/yang-ace/p/18090771