前言
Laravel发布安全更新,其中指出使用cookie session driver的应用受到漏洞影响,该漏洞会导致rce。
https://blog.laravel.com/laravel-cookie-security-releases
影响版本:< v6.18.27,< v7.22.0
Regarding the vulnerability, applications using the “cookie” session driver that were also exposing an encryption oracle via their application were vulnerable to remote code execution. An encryption oracle is a mechanism where arbitrary user input is encrypted and the encrypted string is later displayed or exposed to the user. This combination of scenarios lets the user generate valid Laravel signed encryption strings for any plain-text string, thus allowing them to craft Laravel session payloads when an application is using the “cookie” driver.
Today’s fix prefixes cookie values with an HMAC hash of the cookie’s name before encryption and then verifies a matching hash on decryption, making it impossible to craft a valid cookie payload even if an encryption oracle is exposed via the application.
补丁分析
分析commit历史,发现v7.22.0版本开始修复,但后续又出现了多个版本。
https://github.com/laravel/framework/compare/v7.21.0...v7.22.2
作者的多次补丁
594a3abdec383b55ce32a9e960263f55b41318e2
bb9db21af137344feffa192fcabe4e439c8b0f60
c9ce261a9f7b8e07c9ebc8a7d45651ee1cf86215
5786aa4a388adfcc62862573275bd37d49aa07d7
除第一次补丁外,后续几次都是对cookie加解密方式进行调整。
找到处理加密逻辑的类,初步推测可能是padding oracle 攻击。
解密时如果$unserialize是true,则会对解密后的值进行反序列化,漏洞可能与反序列化有关,但未找到直接调用decrypt并且反序列化的入口。解密前会在getJsonPayload函数中会对mac进行校验,伪造iv或者value都会导致mac校验失败,无法进行padding oracle攻击。
再看看补丁,其中把cookie的key和value拼接到了一起,并且在解密时校验了key。猜测漏洞是由key1生成的加密cookie值,被用到了key2
测试
在本地搭建环境composer create-project laravel/laravel --prefer-dist blog
修改依赖composer.json "laravel/framework": "=7.21.0"
composer update
公告中提到了cookie session driver
,修改本地.env中的配置SESSION_DRIVER=file
重新访问后 session数据被写入cookie,这个字段名是cookie中laravel_session解密后的值,也就是sessionid。此时已知明文、iv、密文,但也解不出key。由于mac校验,也无法使用padding oracle攻击。
跟进一下cookie session还原的过程,在CookieSessionHandler类,从cookie中取出session数据
然后在Store中对session数据进行反序列化,这里的prepareForUnserialize没对数据进行任何处理
漏洞的sink点应该是在这里,控制了cookie中加密的session数据就能进行反序列化从而rce。
看看session中的数据格式,测试代码:
运行结果,打印出了解密后的session数据
现在的主要问题就是如何构造加密的session。
经过分析未找到能够直接构造任意加密session的方式,根据补丁猜测此漏洞可能需要配合开发者的漏洞代码才能利用
测试代码如下:
1 | class TestController extends Controller |
把输入数据作为cookie值,将输入数据设置为 {"expires":1597443282,"data":"O:4:\"Evil\":0:{}"}
(data部分需要构造反序列化调用链),服务端对其加密后返回在cookie中。然后可利用此值作为session数据进行反序列化攻击。
总结
漏洞比较鸡肋,限制条件较多
- 需要开启cookie session driver,默认是file driver
- 需要开发者特定的漏洞代码 cookie(‘key’, $value ,value的值完全可控
- 反序列化调用链
参考文档
https://laravel-news.com/important-laravel-security-updates
http://www.vuln.cn/6315
https://learnku.com/docs/laravel/7.x/lifecycle/7453