Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)

  • A+
所属分类:安全漏洞

Packer-Fuzzer一款针对Webpack等前端打包工具所构造的网站进行快速、高效安全检测的扫描工具


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


0x01定位js执行点


        简单搜索execjs就可以找到执行点,位置在Recoversplit.py的57行


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


0x02 防护绕过

        

        作者在写这个代码的时候也意识到了被反打的可能性(“防止黑吃黑被命令执行”),所以当js出现了exec和spawn的时候就不会执行,但是这样的简单的防护几乎是没有用的。

且不说nodejs沙箱逃逸已经被师傅们玩出花来了,单是这里eval没有过滤掉就可以通过字符串拼接或者url编码的方式绕过这个限制

比如说这里就用了url编码了能弹出计算器的payload,解码并eval之后就能弹出计算器


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


0x03 调用分析


        那么这个执行点是怎么被调用到的呢

看了下代码,发现执行点在RecoverSplit类的jsCodeCompile里,这个函数被同一个类的checkCodeSpilting调用,而checkCodeSpilting又被这个类的recoverStart调用,recoverStart被Project类的parseStart调用,而parseStart,而再往前追溯就是命令参数处理之类乱七八糟的地方了

知道了这些东西之后,我们就可以根据它的调用一步一步走,一点一点写出RCE的POC了


0x04 如何进入recoverStart函数?让程序相信这个网站使用了webpack


我们看到这个parseStart长这样


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


发现如果想要让程序调用recoverStart,就需要让前面的checkStart返回1或者777,这里的checkStart的意思是检查网站是否真的用了webpack技术,如果真的用了才继续扫描下去


checkStart调用了checkHTML,如果能让checkHTML返回1就可以让checkStart返回1


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


跟过去看一下

发现如果返回的html包含了fingerprint_html的某一项就返回1


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


在fingerprint_html中看到了这些片段,可以知道,只需要在html里面包含其中的任意一个片段就可以让扫描器相信网站使用了webpack技术


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


因此在POC的html中,我加入了<noscript>naive!</noscript>来骗过扫描器


0x04 如何进入checkCodeSpilting函数?


recoverStart用于处理js(而不是html了)


        这里并没有加入什么恼人的判断,那个if也只是判断文件后缀名不为db。推测扫描器是先把js下到本地然后再读取的,因此在构造POC的时候,通过script src引入一个js,就可以让它进入到这个函数


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


0x04 如何进入jsCodeCompile函数并把我们想要的东西传入?


    checkCodeSpilting会读取文件,判断是否包含了document.createElement("script");这个字符串(以检查是否有异步加载的js代码),如果是的话再做一个正则匹配,然后把值加一个前缀一个后缀之后传入jsCodeCompile函数


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


想要成功调用jsCodeCompile函数,在js中就得加入document.createElement("script");,而想要传我们想传的参数进去就得研究这个正则了。

        我比较菜,对正则一直心怀恐惧,但是好在这个正则也不难懂,首先匹配一个字母或者数字或者下划线(w),在匹配一个点和一个字母p以及加号(.p+),接着就是匹配到的内容,正则会不断匹配知道遇到一个.和一个字母j以及字母s(.js)

因此实际上就是 这个正则就是匹配如下内容

【随便一个字母数字下划线】p【我们想让他匹配的内容】.js
匹配完了之后,前面加个",后面加个.js,变成jsCode传入jsCodeCompile


0x04 如何在jsCodeCompile函数中实现RCE?


            这个函数是最后也是最重要的函数,它相对复杂,因此需要分几个步骤分析

首先看到这个js执行的地方,它进行了“防止黑吃黑命令执行”的检查之后,首先会去编译这个js,接着从nameList里面取东西然后传入到js中的js_compile函数里。

因此我们要做的就是两件事情,一个是让jsCodeFunc里面变成我们的RCE代码,第二个是让nameList里面有东西可以传进去


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


首先我们来出了让jsCodeFunc有RCE代码的问题

jsCodeFunc的生成过程如下


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


        首先从jsCode中正则匹配出被[]包裹着的第一个内容,作为js_compile函数的参数,然后jsCode本身再被插入进去赋值给作为js_url,看起来工具的作者是希望能够动态解析js以获取url地址

因此为了让里面能够接收一个参数,需要直接在jsCode里面加入一个展开,匹配到之后就会让variable为字母s,这样前面的部分就是js_compile(s),解决了前面传入参数的问题

        接着就要处理如何加入了jsCode之后能执行恶意代码的问题了。

刚才的分析结果表明传入的内容前面被加了个"后面被加了个.js,而且我们还要在传入内容加一个展开,并且加完了这一堆东西之后还不能有问题。

        虽然看起来条件苛刻,实际上处理起来也不复杂,针对前面的",我们再加一个"然后来个;来结束语句即可。接着加入RCE语句,最后为了对付后面的.js和展开,直接用//注释掉

        由于后面拼接的return js_url}前面有个n,因此注释对其不起作用,因此我们不需要自己return一个值然后用大括号闭合


接着我们来处理如何让nameList有值的问题


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


        发现nameList就是匹配了两个正则表达式之后加进来的,因此随便加一个能让某个表达式匹配到内容的字符串就可以了,这里我加的是{114514:,会让第一个正则表达式匹配到114514,并且加入到nameList中

我们把{114514:加入到刚才写的语句的注释中就可以了

以上就是payload的完整生成过程


0x05 RCE展示&POC


Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)


地址:

https://github.com/TomAPU/poc_and_exp/tree/master/Packer-Fuzzer-RCE


文献:

https://drivertom.blogspot.com/2021/01/packer-fuzzerrce-0day.html?m=1


本文始发于微信公众号(Khan安全团队):Packer-Fuzzer漏扫工具RCE 0day(当前已被官方修复)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: