js原型链污染
基础概念辨析
原型
js中一切皆对象,js的每个对象都有一个属性原型(prototype),原型本身也是一个对象,因此该原型也有一个prototype指向上层原型,直到为null,这样就构成了原型链
简单来说,原型链是javascript中类继承的一种机制,每个对象都有对应的原型,储存了定义的属性和方法,之中包含了prototype,指向上一级的原型。最上层Object原型中的prototype为null
特性
类定义中的属性,会在创建对象时在对象中创建,类定义的方法而是存在于原型之中。当使用没有定义的属性和方法时,就会顺着原型链一直寻找,直到为undefined,用此来实现继承,子类能用父类的属性和方法
示例
function Person(name) { |
person1对象原型对象展示
prototype与__proto__
(1)所有引用类型(函数,数组,对象)都拥有__proto__
属性(隐式原型),用来查看其原型
(2)所有函数拥有prototype
属性(显式原型)(仅限函数)
简单来说,proto 属性是指向该对象的原型,而 prototype属性是用于创建该对象的构造函数的原型。
Function 与function
function是一个定义函数的关键字,Function是代表所有函数的内置原型对象
每一个js 的function都是Function对象,Function是js内置对象,用以实现很多基本功能,如Nunmber,toString
constructor是一个对象数据属性属性,创建对象后,访问constructor属性,可以返回构造该对象的来源(不是该对象的原型链上级)
new
new constructor[([arguments])]
参数
constructor
一个指定对象实例的类型的类或函数。
描述
new
关键字会进行如下的操作:
- 创建一个空的简单 JavaScript 对象(即
{}
); - 为步骤 1 新创建的对象添加属性
__proto__
,将该属性链接至构造函数的原型对象; - 将步骤 1 新创建的对象作为
this
的上下文; - 如果该函数没有返回对象,则返回
this
。
原型链污染
当我们添加或者修改上层原型的一些属性,子类都又调用该恶意属性时,子类调用的属性已经被我们篡改,造成原型链污染,原型链污染可能会造成命令执行(rce)或者任意文件读取,越权等等
示例
function merge(target, source) { |
漏洞点
一般对对象进行复制拷贝,如merge函数或者copy函数,会将传入的json数据拷贝至已创建对象,此时可能会产生原型链污染
ejs模板基于原型链污染的rce
直接上POC
a; return global.process.mainModule.constructor._load('child_process').execSync('whoami'); // |
扩展
对于toUpperCase()
函数
字符"ı"、"ſ" 经过toUpperCase处理后结果为 "I"、"S" |
对于toLowerCase
字符"K"经过toLowerCase处理后结果为"k"(这个K不是K) |
详情可见p神的文章https://www.leavesongs.com
python中也存在原型链污染
可参考文章:https://tttang.com/archive/1876
防御
1.Object.freeze()冻结原型
Object.freeze(Object.prototype); |
冻结原型后,无法添加新的原型至原型链
2.对JSON输入验证
npm上有很多库,如avj,可以对JSON数据验证,排除json中数据中不需要的属性
或者在复制对象时,遍历键名时候,检查__proto__和prototype
3.使用map代替{}
4.使用Object.create()安全创建对象
这样创建的对象没有属性
5.node.js中可以通过disable-proto直接禁止操作原型链