Skip to content

Keamanan: Cegah RCE via Theme Hook include_once dan Backtick Operator Bypass pada ThemeHooksValidator - #1715

Open
habibie11 wants to merge 1 commit into
rilis-devfrom
dev-57-keamanan-rce-theme
Open

Keamanan: Cegah RCE via Theme Hook include_once dan Backtick Operator Bypass pada ThemeHooksValidator#1715
habibie11 wants to merge 1 commit into
rilis-devfrom
dev-57-keamanan-rce-theme

Conversation

@habibie11

@habibie11 habibie11 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

issue # https://github.com/OpenSID/wiki-keamanan/issues/57

🎯 Deskripsi

Pull request ini memperbaiki kerentanan keamanan kritis Remote Code Execution (RCE) (CWE-94 / CWE-96, OWASP A03:2021) pada modul manajemen tema OpenDK.

Penyebab Masalah:

  1. Pengecekan Token Melewati Karakter Tunggal: Komponen ThemeHooksValidator::validateSource() memvalidasi file hooks.php menggunakan fungsi bawaan PHP token_get_all(). Pada implementasi sebelumnya, perulangan token dimulai dengan baris if (! is_array($tokens[$i])) continue;. Hal ini menyebabkan semua token karakter tunggal (seperti backtick `, $, (, ), ;) dilewati tanpa diperiksa sama sekali.
  2. Backtick Execution Operator Bypass: Di PHP, tanda petik terbalik (backtick `cmd`) merupakan operator eksekusi sistem yang identik dengan fungsi shell_exec('cmd'). Karena karakter backtick terlewat dari validasi token, perintah sistem seperti `id > themes/default/rce_proof.txt 2>&1` lolos dari filter.
  3. Eksekusi Otomatis: Saat tema diaktifkan melalui ThemesController::activate() -> ThemeService::activate() -> ThemeHooksValidator::loadHooks(), file hooks.php dimuat menggunakan include_once $hooksFile, sehingga perintah sistem yang disuntikkan langsung dieksekusi di bawah hak akses user web server (www-data).
  4. Celah Potensial Lainnya: File hooks.php dan arsip ZIP tema sebelumnya belum memvalidasi secara ketat konstruksi bahasa lain seperti include/require (T_INCLUDE*, T_REQUIRE*), dynamic class instantiation (new $class()), dynamic static/member calls ($obj->$method(), Class::$method()), variasi variable variables ($$var), pemindaian .blade.php berbahaya di arsip ZIP, serta fungsi-fungsi manipulasi berkas/direktori/eksekusi proses PHP lainnya.

Solusi yang Diterapkan:

  1. Multi-Layer Defense pada ThemeHooksValidator::validateSource():
    • Lapisan 1 (Raw String Scan): Memeriksa langsung string sumber menggunakan str_contains($source, '')` dan langsung menolak berkas jika ditemukan karakter backtick.
    • Lapisan 2 (AST & Token Analysis): Menghapus pelewatan non-array token dan memeriksa secara detail setiap token literal karakter tunggal maupun array token.
    • Blokir Konstruk Bahasa Berbahaya: Mendeteksi dan menolak token T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE, T_EVAL, dan T_HALT_COMPILER.
    • Blokir Pemanggilan Dinamis: Mendeteksi dan menolak new $class(), $obj->$method(), Class::$method(), $$var, serta variable function call ($f()) lengkap dengan mitigasi bypass komentar/whitespace.
    • Perluasan DANGEROUS_FUNCTIONS: Menambahkan fungsi kontrol proses (pcntl_*), callback dinamis (forward_static_call, register_shutdown_function, dll), pembacaan berkas & direktori (readfile, file, scandir, glob, dll), serialisasi (unserialize), serta fungsi obfuskasi (hex2bin, gzinflate, dll).
  2. Pengamanan Arsip ZIP Tema (scanZipForPhp):
    • Memastikan file .blade.php hanya diizinkan jika berada di direktori resources/views/.
    • Memindai konten .blade.php di dalam arsip ZIP untuk memastikan tidak disusupi operator backtick pada blok arahan PHP/Blade (<?php, @php, {{, {!!) sebelum diekstrak, tanpa memblokir JavaScript ES6 template literals murni pada sisi frontend (mencegah false positive pada tema modern seperti buen).
  3. Pengujian Komprehensif:
    • Menambahkan 33 unit tests pada ThemesControllerSecurityTest.php dan 13 feature tests pada ThemeUploadSecurityTest.php.

🛠️ Perubahan yang Dilakukan

1. app/Services/ThemeHooksValidator.php

Fix — Penguatan validasi token AST, pencegahan backtick, dan pengamanan arsip ZIP tema:

  • Memperluas daftar DANGEROUS_FUNCTIONS dan mendefinisikan DANGEROUS_LANGUAGE_TOKENS.
  • Menambahkan pemeriksaan lapis ganda untuk backtick operator dan konstruksi dinamis.
  • Mengamankan pemindaian ZIP untuk file template .blade.php dengan deteksi terarah pada arahan PHP/Blade.
     private const DANGEROUS_FUNCTIONS = [
+        // OS command & process execution
         'system', 'exec', 'passthru', 'shell_exec', 'popen', 'proc_open',
-        'pcntl_exec', 'assert', 'create_function', 'eval',
-        // BUG FIX: call_user_func / call_user_func_array bypass (Severity: Critical)
+        'pcntl_exec', 'pcntl_fork', 'pcntl_alarm', 'pcntl_signal', 'pcntl_wait',
+        'pcntl_waitpid', 'pcntl_wexitstatus', 'dl', 'assert', 'create_function', 'eval',
+        // Dynamic callback & indirect invocation
         'call_user_func', 'call_user_func_array',
+        'forward_static_call', 'forward_static_call_array',
+        'register_shutdown_function', 'register_tick_function',
+        'preg_replace_callback', 'preg_replace_callback_array', 'mb_ereg_replace_callback',
+        'array_map', 'array_filter', 'array_reduce', 'array_walk', 'array_walk_recursive',
+        'unserialize',
+        // File system & I/O
         'file_put_contents', 'file_get_contents', 'fopen', 'fwrite', 'fputs',
         'unlink', 'mkdir', 'rmdir', 'rename', 'copy', 'chmod', 'chown',
-        'symlink', 'link', 'tmpfile', 'move_uploaded_file',
+        'symlink', 'link', 'tmpfile', 'move_uploaded_file', 'touch',
+        'readfile', 'file', 'fpassthru', 'highlight_file', 'show_source',
+        'fileperms', 'fileowner', 'filegroup', 'chgrp', 'lchown', 'lchgrp',
+        'glob', 'scandir', 'opendir', 'readdir', 'dir',
+        // Environment, configuration & variable manipulation
         'extract', 'parse_str', 'putenv',
         'ini_set', 'ini_alter',
         'header', 'setcookie',
         'define', 'defined',
-        'base64_decode', 'urldecode',
+        // Encoding / Obfuscation helpers
+        'base64_decode', 'urldecode', 'hex2bin',
+        'gzinflate', 'gzuncompress', 'gzdecode', 'str_rot13', 'convert_uudecode',
+    ];
+
+    /**
+     * Dangerous PHP language construct tokens that are blocked in hooks.php.
+     */
+    private const DANGEROUS_LANGUAGE_TOKENS = [
+        T_EVAL,
+        T_INCLUDE,
+        T_INCLUDE_ONCE,
+        T_REQUIRE,
+        T_REQUIRE_ONCE,
+        T_HALT_COMPILER,
     ];
             // Validate Blade template files
             if (str_ends_with($filename, '.blade.php')) {
+                // Blade templates must be inside resources/views/
+                if (! str_contains($filename, 'resources/views/')) {
+                    $dangerousFiles[] = "{$filename} (Blade template must reside in resources/views/)";
+                    continue;
+                }
+
+                // Scan Blade content for PHP/Blade execution blocks containing backtick operator
+                $bladeContent = $zip->getFromIndex($i);
+                if ($bladeContent !== false && preg_match('/(<\?php|@php|\{\{|\{!!)[^>}]*`/', $bladeContent)) {
+                    $dangerousFiles[] = "{$filename} (Backtick execution operator detected in PHP/Blade directive)";
+                    continue;
+                }
+
                 continue;
             }

2. tests/Unit/ThemesControllerSecurityTest.php

Test — Penambahan Unit Test Keamanan untuk ThemeHooksValidator:

  • Menambahkan pengujian untuk backtick operator (simple, live PoC payload, dan assignment).
  • Menambahkan pengujian untuk konstruk bahasa (include, include_once, require, require_once).
  • Menambahkan pengujian untuk pemanggilan dinamis (new $class(), $obj->$method(), Class::$method(), $$var, variable function dengan komentar).
  • Menambahkan pengujian untuk fungsi berbahaya tambahan (readfile, forward_static_call, register_shutdown_function, unserialize, scandir, glob).
  • Menambahkan pengujian untuk validasi .blade.php pada arsip ZIP (lokasi, penolakan backtick pada arahan PHP/Blade, dan izin untuk JavaScript ES6 template literals).

3. tests/Feature/Security/ThemeUploadSecurityTest.php

Test — Penambahan Feature Test Keamanan untuk Aktivasi & Upload Tema:

  • Menambahkan pengujian aktivasi tema dengan payload backtick di hooks.php (memastikan redirect dengan error dan tidak membuat file rce_proof.txt).
  • Menambahkan pengujian aktivasi tema dengan payload include di hooks.php.
  • Menambahkan pengujian upload tema ZIP yang mengandung backtick pada direktif Blade.
  • Menambahkan pengujian upload tema ZIP yang meletakkan .blade.php di luar direktori resources/views/.

✅ Test Cases yang Diimplementasikan

  • File hooks.php yang mengandung backtick execution operator (`id` atau `id > rce_proof.txt`) ditolak secara otomatis dan tidak dieksekusi.
  • File hooks.php yang mengandung konstruk include, include_once, require, atau require_once ditolak secara otomatis.
  • Pemanggilan fungsi dinamis seperti $f(), new $class(), $obj->$method(), Class::$method(), dan $$var ditolak.
  • Pemanggilan fungsi berbahaya tambahan (readfile, forward_static_call, register_shutdown_function, unserialize, scandir, glob) ditolak.
  • Upload tema ZIP dengan file .blade.php di luar resources/views/ atau mengandung operator backtick di direktif PHP/Blade ditolak.
  • Upload tema ZIP dengan sintaks JavaScript ES6 template literals (backtick) pada template Blade tetap diizinkan dan berjalan normal.
  • Tema valid tanpa kode berbahaya tetap dapat diunggah dan diaktifkan dengan sukses.
  • Semua 33 unit tests di ThemesControllerSecurityTest.php dan 13 feature tests di ThemeUploadSecurityTest.php lulus 100%.

🤖 Cara Menjalankan Uji Coba Otomatis (Automated Test)

Untuk menjalankan seluruh rangkaian automated test keamanan yang ditambahkan pada PR ini, jalankan perintah berikut di terminal:

# Menjalankan Unit Tests keamanan ThemeHooksValidator
php artisan test tests/Unit/ThemesControllerSecurityTest.php

# Menjalankan Feature Tests keamanan upload dan aktivasi tema
php artisan test tests/Feature/Security/ThemeUploadSecurityTest.php

# Menjalankan seluruh regression test keamanan
php artisan test tests/Feature/Security/SecurityTest.php

📸 Cara Menjalankan Uji Coba Manual

  1. Masuk ke halaman admin OpenDK sebagai Super Admin.
  2. Buat berkas uji themes/default/hooks.php dengan isi payload PoC:
    <?php
    `id > themes/default/rce_proof.txt 2>&1`;
  3. Buka menu Pengaturan > Tema (/setting/themes).
  4. Klik tombol Aktifkan pada tema default.
    • Hasil yang Diharapkan: Halaman dialihkan dengan pesan error "Tema diaktifkan tetapi hooks.php ditolak: hooks.php mengandung kode berbahaya: Backtick execution operator is not allowed".
    • Verifikasi: Periksa direktori themes/default/, pastikan berkas rce_proof.txt TIDAK pernah tercipta (perintah OS tidak dijalankan).
  5. Hapus berkas themes/default/hooks.php setelah pengujian selesai.

⚠️ Catatan Penting

Modifikasi ini menerapkan prinsip defense-in-depth. Validasi dilakukan pada tingkat raw source code dan parsing token sintaks AST PHP. File hooks.php pada tema tetap didukung untuk mendefinisikan fungsi murni dan konfigurasi array murni yang aman, serta template Blade tetap kompatibel penuh dengan JavaScript modern (ES6 template literals).

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI PR Review sedang antri di server...

Proses review akan segera dimulai di background — hasil akan muncul sebagai komentar setelah selesai.
Powered by CrewAI · PR #1715

@habibie11
habibie11 requested a review from vickyrolanda August 31, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant