jade原型链污染RCE
Last updated on October 24, 2023 pm
题源CTF SHOW Web342
jade原型链污染RCE
1.分析
下载源码,拖入IDEA,在bin/www.js启动调试,在routes/index.js下断点,然后访问127.0.0.1:3000,触发断点,开始调试

跟入res.render函数

继续跟入app.render函数

继续跟入tryRender函数

继续跟入view.render函数

继续跟入this.engine函数

继续跟入exports.renderFile函数

走一个小递归,然后进入handleTemplateCache函数

跟进exports.compile函数

重点关注204行的parse函数,这个函数返回值给parsed,然后parsed拼接进fn,fn再送进218行的Function执行,那么就要想办法让parsed代入我们自己的命令,跟入parse函数

这里先走104行的parse函数,再走114行的compile函数,得到的js拼接进body然后返回

104行的parse函数操作空间不大,跟进114行的compile函数

继续跟进66行的this.visit函数

发现有可控的地方,只要能进入198行的语句,就可以把node.linepush进buf。
对这个this.debug进行溯源跟踪,查看是否可控,确保其一定能进入if判断
在由this.engine进入的函数里出现相关字段

且是undefined,也就是可以污染,继续往下跟进,看哪里赋值给this
最终发现是在index.js/parse()函数里的111行,创建了一个compile对象时给的值

跟进去查看

正好,还是undefined,而且赋值也简单,因此可以构造exp确保this.debug为true
这里顺带把line也一起污染了,这样可以保证后期的payload一定能执行
1 | |
随便找一个对象,查看它的原型,看看是否污染成功

可以发现,object以及带上被污染的属性了,继续往下走

node.line也如预期一样被污染,继续执行
报错

依据报错信息,进入compiler.js的225行查看

调试发现,当node为刚刚污染的语句时,node.type为undefined,进而引发报错

考虑继续污染node.type,那就直接污染成Block吧,跟上一个节点一样
1 | |
继续报错

跟入compiler.js的283行查看

就是283行那几句出问题,那就继续污染这几个变量
1 | |
继续报错

前4点依旧处于jade模块,在jade模块中,最终报错点在index.js的149行

尝试污染options.self为true,进而避免进入149行,看能不能解决此问题
1 | |
Bingo!,成功弹shell

2.exp
1 | |
也有更稍微简短的exp(也就是换了一个Block节点)
1 | |
NOTE:如果POST的数据没有接收到,看看HTTP头有没有Content-Type: application/json,没有的话加一个(本地做的时候,没有这个字段)