Laravel Debug模式下远程代码执行漏洞分析​

2021-01-15 14:53:442325人阅读

1、前言


2021年1月13日,百度云安全团队监测到有国外安全研究人员披露了Laravel远程代码执行漏洞详情,当Laravel<=8.4.2、ignition组件版本<=2.5.1并且开启了Debug模式情况下,攻击者可通过php://filter构造特定的日志文件,并触发Phar反序列化导致任意代码执行漏洞,漏洞危害较大,建议及时升级Laravel以及ignition组件到最新版本。


2、漏洞环境搭建


git clone https://github.com/laravel/laravel.git  #下载laravel源码

cd laravel

git checkout -b e849812      #切换到存在漏洞的分支

composer install       #composer安装依赖

composer require facade/ignition==2.5.1    #下载存在漏洞版本组件


安装好后在根目录执行 mv .env.example .env,.env.example中默认设置了APP_DEBUG=true,此时启动apache2服务器即可。


为了复现原作者所述当变量未定义时出现的报错情况,需要在resource/views/ hello.blade.php中设置一个简单的模板。

图片4.png

并在routes/web.php中添加路由


图片5.png


访问/public/index.php/hello即出现变量未定义的报错信息。


图片6.png


3、漏洞分析


点击Make variable optionl并抓包,请求的接口为/_ignition/execute-solution


图片7.png


通过搜索路由,对应的处理类为ExecuteSolutionController,由于此处类对象被当做函数调用,因此会调用ExecuteSolutionController类的__invoke方法。


图片8.png


在__invoke中,先调用ExecuteSolutionRequest->getRunnableSolution()获取solution对象,随后调用solution对象的run方法。


图片9.png


但此时需要知道solution对象对应的类,因此跟进到getRunnableSolution方法,发现solution对象来自getSolution方法的返回,并且必须是RunnableSolution类的实例,也就是说solution对象的类必须是RunnableSolution类的子类。跟进getSolution方法,发现类来源于传递的solution参数,而solution的值为Facade\Ignition\Solutions\MakeView VariableOptionalSolution恰好继承于RunableSolution接口,满足上述条件。


图片10.png


跟进到MakeViewVariableOptionalSolution的run方法,可以看到$parameters参数被传递到makeOptional参数处理,并且viewFile参数对应的文件会被file_get_contents方法读取,并将$username替换为$username ? ‘’,并且由于后续会做Token化比对,因此没办法直接通过控制variableName参数做一些突破。


图片11.png


但由于viewFile可控,并且会经过file_get_contents方法处理,如果能够上传或者写入Phar文件,是可以利用phar://实现反序列化的。而此时我们唯一可控部分内容的文件是laravel的日志文件,默认目录是storage/logs/laravel.log。


此时就算能控制一部分日志内容,但可控内容前后有日期、堆栈信息等太多不可控内容,没办法直接写入Phar文件。这时候,漏洞原作者巧妙的利用了php://filter伪协议,该协议能够灵活地对文件内容进行多种编解码。


利用base64解码能够在有一部分干扰内容情况下仍然解码成功,但如果有=等字符则可干扰正常解码。此时作者想到了利用convert.iconv.utf-16le.utf-8,可以将其他干扰内容转换成非ascii,而非ascii字符再经过base64解码即可变成空。但utf-16le编码中会有一些空字符,传递到file_get_contents方法中会报错。因此还需要利用convert.quoted-printable-encode可以将空字符编码为=00,再使用与之相对的decode方法即可解决这个问题。


因此整体的调用链条如下:

ExecuteSolutionController->__invoke()

->ExecuteSolutionRequest->getRunnableSolution()->getSolution()

->MakeViewVariableOptionalSolution->run()


4、漏洞利用


在了解上述原理后,想要利用该漏洞需要有几个步骤:


1)清空laravel.log


设置viewfile=php://filter/write=convert.base64-decode|convert.base64-decode|convert.base6 4-decode/resource=/var/www/html/laravel/storage/logs/laravel.log


并多执行几次,利用base64解码失败输出为空的特性将日志置空。


图片12.png


2)向日志中插入特定的Payload


利用phpggc项目选择特定的反序列化链条生成Payload,并根据上述分析做三重对应的编码。


图片13.png


3)日志内容解码


利用convert.quoted-printable-decode、convert.iconv.utf-16le.utf-8、convert.base64-decode三种方式解码,确保日志中仅存Phar文件。


图片14.png


4)触发Phar反序列化


当Phar文件被部分文件系统函数处理时触发反序列化,此处利用Larvavel特定依赖monolog的反序列化利用链实现任意代码执行。


图片15.png


5、安全产品解决方案


百度度御关WAF、高级威胁感知系统,以及智能威胁狩猎平台已支持该漏洞的检测和拦截,有需要的用户可以访问anquan.baidu.com联系我们。


参考:

https://www.ambionics.io/blog/laravel-debug-rce


本文由百度安全原创,转载请注明来源。

0
现金券
0
兑换券
立即领取
领取成功