2021-01-15 14:53:4410256人阅读
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中设置一个简单的模板。
并在routes/web.php中添加路由
访问/public/index.php/hello即出现变量未定义的报错信息。
3、漏洞分析
点击Make variable optionl并抓包,请求的接口为/_ignition/execute-solution
通过搜索路由,对应的处理类为ExecuteSolutionController,由于此处类对象被当做函数调用,因此会调用ExecuteSolutionController类的__invoke方法。
在__invoke中,先调用ExecuteSolutionRequest->getRunnableSolution()获取solution对象,随后调用solution对象的run方法。
但此时需要知道solution对象对应的类,因此跟进到getRunnableSolution方法,发现solution对象来自getSolution方法的返回,并且必须是RunnableSolution类的实例,也就是说solution对象的类必须是RunnableSolution类的子类。跟进getSolution方法,发现类来源于传递的solution参数,而solution的值为Facade\Ignition\Solutions\MakeView VariableOptionalSolution恰好继承于RunableSolution接口,满足上述条件。
跟进到MakeViewVariableOptionalSolution的run方法,可以看到$parameters参数被传递到makeOptional参数处理,并且viewFile参数对应的文件会被file_get_contents方法读取,并将$username替换为$username ? ‘’,并且由于后续会做Token化比对,因此没办法直接通过控制variableName参数做一些突破。
但由于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解码失败输出为空的特性将日志置空。
2)向日志中插入特定的Payload
利用phpggc项目选择特定的反序列化链条生成Payload,并根据上述分析做三重对应的编码。
3)日志内容解码
利用convert.quoted-printable-decode、convert.iconv.utf-16le.utf-8、convert.base64-decode三种方式解码,确保日志中仅存Phar文件。
4)触发Phar反序列化
当Phar文件被部分文件系统函数处理时触发反序列化,此处利用Larvavel特定依赖monolog的反序列化利用链实现任意代码执行。
5、安全产品解决方案
百度度御关WAF、高级威胁感知系统,以及智能威胁狩猎平台已支持该漏洞的检测和拦截,有需要的用户可以访问anquan.baidu.com联系我们。
参考:
https://www.ambionics.io/blog/laravel-debug-rce