浅析CTF中的Node.js原型链污染
前言
Node.js之前并未有太多了解 ,浅析最近遇上了一些相关题目,型链发现原型链污染是污染其一个常考点,在学习后对其进行了简单总结 ,浅析希望对正在学习的型链师傅有所帮助
Node.js
原型链污染
首先强推这篇文章https://developer.mozilla.org/,读完后就会对原型链有个大致的污染了解 ,对后面学习非常有帮助。浅析所以说什么是型链原型链污染呢 ?
偏官方一点的解释如下
在JavaScript中,每个对象都有一个原型,污染它是浅析一个指向另一个对象的引用。免费模板当我们访问一个对象的型链属性时 ,如果该对象没有这个属性,污染JavaScript引擎会在它的浅析原型对象中查找这个属性。这个过程会一直持续 ,型链直到找到该属性或者到达原型链的污染末尾。攻击者可以利用这个特性 ,通过修改一个对象的原型链,来污染程序的行为 。例如 ,攻击者可以在一个对象的原型链上设置一个恶意的模板下载属性或方法,当程序在后续的执行中访问该属性或方法时 ,就会执行攻击者的恶意代码 。
简单的说呢 ,其实就是我们对原链中的某个属性进行了污染 ,向其中插入恶意代码,当我们再调用这个链(也就是使用这个对象)时,我们的恶意代码就会被触发,此时就达到了一个执行恶意代码的云计算效果 。说到原型链污染 ,那就肯定离不开__proto__和prototype,所以接下来我们需要了解一下这两个是什么东西。
__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"1.2.3.4.5.6.7.8.9.10.在例子中,我们创建了一个名为 Person的服务器租用构造函数 ,并将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); // 输出 true1.
总结(摘自https://www.leavesongs.com)1、prototype是一个类的属性 ,所有类对象在实例化的时候将会拥有prototype中的属性和方法2 、一个对象的__proto__属性 ,指向这个对象所在的类的prototype属性
他们的关系图如下所示

那么什么是原型链污染呢我们这里用一个简单例子来对其进行说明
复制var a = { number : 520}var b = { number : 1314}b.__proto__.number=520var c= { }c.number1.2.3.4.5.
对这里的情况需要进行简单说明,我们可以看到在我们进行b.__proto__.number=520 操作后,即使是内容为空的c ,调用number属性仍存在且值为我们设定的520,这时就达到了一个原型链污染的目的。接下来再说一下可能部分师傅有疑问的点
一、为什么执行过b.__proto__.number=520 后,我们输出b的值 ,其值仍为1314
这是因为在JavaScript中存在这样一种继承机制:我们这里调用b.number时 ,它的具体调用过程是如下所示的
复制1