Skip to content

浅学原型链污染

js中可以直接定义一个构造函数来创建一个实例

1
2
3
4
function Dashing(){
this.bug = "wudi"
}
d = new Dashing()

js中每个对象都有其原型(即[[Prototype]])(类似于Java中的父类),当调用一个实例的属性或方法时,就会在其自身属性或其_proto_(即[[Prototype]])中去找,_proto_找不到就去_proto_._proto_中找依此类推

Dashing是一个构造函数,Dashing._proto_ 大部分时候指向Function.prototype

什么是prototype?

就是一个构造函数想要其实例有什么属性或方法都会写在construct.prototype属性里面,这样创建每个实例时就不用重复将属性或方法写在实例的属性里了,节省了内存。每个prototype都有constructor属性,指向构造函数自身

像上方代码块中创建的d实例,d._proto_ =Dashing.prototype。

Dashing.prototype._proto_=d._proto_._proto_

继承语法

1
2
3
4
5
6
7
function Dashing(){
}
function Bug(){
}
Object.setPrototypeof(Dashing.prototype,Bug.prototype)
d = new Dashing()
#d.__proto__ = Dashing.prototype, d.__proto__.__proto__=Bug.即将Bug.prototype赋给了Dashing.prototype.__proto__

如果想改变prototype的属性

1
2
3
4
5
function Dashing(){
}
Dashing.prototype.foo = 1;
d = new Dashing();
#这样d.__proto__.foo就等于1

Object.create()会创建一个新对象,函数第一个参数就是新对象的[[Prototype]]的值

1
2
a = {'a': 1};
b = Object.create(a);#b.[[Prototype]]=a

什么是原型链污染?

举个例子🌰:

1
2
3
4
5
a={'number':1}
b={}
a.__proto__.number=2
console.log(a.number)#1
console.log(b.number)=2

其实就是通过改变某个对象原型链上的原型,使其他有这个原型的原型链也被改变了

实例对象的__proto__实际上是对constructor.prototype的引用,这俩共享同一内存地址,一个改变另一个就跟着改变

js大小写特性

对于toUpperCase函数

1
字符"ı"、"ſ" 经过toUpperCase处理后结果为 "I"、"S"

对于toLowerCase

1
字符"K"经过toLowerCase处理后结果为"k"(这个K不是K)

参考:浅析CTF中的Node.js原型链污染 - FreeBuf网络安全行业门户

About this Post

This post is written by DashingBug, licensed under CC BY-NC 4.0.