Antwa CodeAntwaCode Blog

Rekayasa16 menit baca

PHP2Shell: Panduan Lengkap RCE Kritis di Jantung PHP — Berita, Root Cause, dan Cara Mengamankan Server

Dua RCE kritis di inti engine PHP (CVE-2026-109618 & CVE-2026-109619) kini dieksploitasi masif di internet. Panduan lengkap: berita, root cause Zend engine, cara cek & patch server, mitigasi sementara, dan deteksi serangan.

Baca dalam English →

php-src repository Gambar: GitHub — repositori php/php-src, tempat bug PHP2Shell hidup lebih dari 7 tahun

Baru-baru ini dunia PHP digemparkan oleh dua vulnerability kritis yang dijuluki PHP2Shell. Ini bukan bug di framework Laravel, bukan di plugin WordPress, dan bukan di kode aplikasi kamu — melainkan di mesin PHP-nya sendiri. Artinya, situs "Hello World" yang cuma nge-echo satu kalimat pun bisa diserang dengan cara yang persis sama seperti aplikasi enterprise yang kompleks.

Dua celah ini — CVE-2026-109618 dan CVE-2026-109619 — memungkinkan penyerang tanpa akun, tanpa sesi, dan tanpa interaksi sama sekali untuk menjalankan perintah sistem di web server kamu lewat satu request HTTP biasa. Keduanya dinilai CVSS v4.0 9.2 (Critical).

Di artikel ini kita akan membahas semuanya secara lengkap: apa yang terjadi, kronologi kebocorannya yang dramatis, bedah teknis akar masalahnya di Zend engine, daftar versi yang terdampak, sampai langkah-langkah praktis untuk mempatch dan mengamankan server kamu.

Apa Itu PHP2Shell?

PHP2Shell adalah nama kolektif yang diberikan oleh peneliti keamanan — bukan oleh tim PHP — untuk dua remote code execution (RCE) vulnerability di core runtime PHP:

  • CVE-2026-109618 — RCE via OOM corruption: penanganan out-of-memory (OOM) bisa memutus eksekusi PHP di tengah jalan saat data internal request baru terinisialisasi sebagian. Proses cleanup setelahnya membaca data yang belum valid tersebut seolah-olah data itu sah.
  • CVE-2026-109619 — RCE via stale global state: state internal milik sebuah request bisa "tertinggal" setelah memorinya dibebaskan. Request berikutnya yang ditangani oleh worker yang sama memakai state basi tersebut sebelum inisialisasi normal sempat meresetnya (use-after-free).

Keduanya ditemukan oleh tim Wiz Research, OpenAI (Codex Security), dan Calif, dan dilaporkan secara koordinatif ke tim keamanan PHP. Yang menarik, baik Wiz maupian Calif menyatakan mereka memakai model AI dalam risetnya — dan tim Google Gemini juga dilibatkan dalam proses perbaikannya.

Fakta-fakta kunci:

  • Unauthenticated RCE — cukup satu request POST anonim, tanpa login, tanpa CSRF token, tanpa input aplikasi.
  • Tidak peduli seberapa bersih kode aplikasi kamu — serangan terjadi sebelum satu baris kode aplikasi pun dikompilasi.
  • Sangat senyap — worker tidak crash, server mengembalikan HTTP 200, dan log aplikasi bersih.
  • Affect hampir semua versi PHP dari 5.4 sampai 8.5. Bug-nya sudah ada di kode PHP selama lebih dari 7 tahun.
  • Selain RCE, attacker juga bisa membaca memori proses PHP yang bisa berisi password, API key, token, dan sertifikat milik request lain.

Kronologi: Bocor di Hacker News, Rilis Dipercepat Sehari

Cerita di balik PHP2Shell ini seru banget kalau diikuti. Berikut garis waktunya:

  • Agustus 2026 — Peneliti dari Wiz, OpenAI Codex Security, dan Calif menemukan kedua vulnerability dan mulai bekerja sama dengan tim keamanan PHP untuk menyiapkan perbaikan. Detail dijaga rapat-rapat di bawah embargo.
  • 20 Oktober 2026 — Sebuah postingan di Hacker News membocorkan dua CVE identifier ini, mengklaim skor CVSS 10.0 dan dampak ke PHP versi 5 ke atas, hanya bermodal "source: trust me, bro". Tim PHP langsung merilis advance notice malam itu juga (19:33 UTC) dan menjadwalkan rilis keamanan pada 21 Oktober pukul 14:00 UTC — sehari lebih cepat dari jadwal disclosure aslinya yang 22 Oktober.
  • 21 Oktober 2026, 03:02 UTC — Cloudflare sudah menyalakan WAF rules darurat untuk semua pelanggannya (termasuk paket gratis) sebelum patch-nya sendiri rilis.
  • 21 Oktober 2026, beberapa jam sebelum rilis — Hadrian melaporkan eksploitasi PHP2Shell "in the wild at scale", mayoritas memanfaatkan jalur session upload progress.
  • 21 Oktober 2026, 14:00 UTC — PHP merilis patch darurat: 8.5.12, 8.4.27, 8.3.36, dan 8.2.35, lengkap dengan advisory teknis untuk kedua CVE.
  • 21 Oktober 2026, 14:19 UTC — watchTowr mengonfirmasi melihat "active exploitation attempts" untuk kedua vulnerability. Cloudflare melaporkan attacker terus mengganti payload untuk menembus firewall rules mereka.
  • 21 Oktober 2026 — CISA menerbitkan alert "Critical Vulnerabilities in PHP Require Immediate Patching".

Catatan soal skor: klaim CVSS 10.0 yang beredar di Hacker News itu bukan skor resmi. Tim PHP menilai kedua vulnerability dengan 9.2 di CVSS v4.0. Tetap kritis, tetap harus segera dipatch, tapi mari pakai angka yang resmi.

Sampai saat berita ini ditulis, belum ada konfirmasi keberhasilan break-in ke server tertentu — tapi volume percobaan serangannya sudah masif. Prinsipnya sederhana: kalau belum patch, anggap saja server kamu sudah dalam jangkauan scanner.

Kenapa PHP2Shell Sangat Berbahaya

1. Salahnya Bukan di Kode Kamu

Ini poin paling penting dan paling menakutkan. PHP memproses data request yang masuk sebelum ekstensi diinisialisasi dan sebelum satu baris kode aplikasi dikompilasi. Jadi eksploitasinya benar-benar independen dari apa pun yang di-host server kamu.

Apakah aplikasi kamu ditulis dengan sempurna, lulus audit keamanan, dan pakai framework terbaru? Tetap kena. Apakah server kamu masih menjalankan CMS bobrok yang ditinggalkan developer 5 tahun lalu? Juga kena, dengan tingkat paparan yang persis sama. Seperti kata CrowdStrike: "A meticulously maintained application is exposed to precisely the same degree as a neglected one."

2. Serangannya Senyap

Worker yang dieksploitasi tidak crash. Server mengembalikan respons HTTP 200 yang normal. Log aplikasi tidak mencatat apa pun yang aneh. Kalaupun terjadi error, fatal error PHP tidak selalu tercatat di tempat yang kamu cek. Ini membuat deteksi berbasis log menjadi sulit dan membuat attacker bisa bolak-balik mencoba tanpa ketahuan.

3. Cukup Satu Request

Untuk mod_php, exploit yang sudah terbukti bekerja hanya butuh satu request POST anonim. Tidak perlu sesi, tidak perlu otentikasi, tidak perlu interaksi user. N-day scanning tinggal menembakkan payload ke semua target dan melihat mana yang "menggigit".

4. Dampaknya Dua Arah

Selain menjalankan perintah (RCE), CVE-2026-109619 juga terbukti memungkinkan memory disclosure — membaca isi memori proses PHP worker. Kenapa ini bahaya? Karena memori worker bisa berisi kredensial database, API key, token autentikasi, dan sertifikat yang sedang dipakai request lain yang kebetulan lewat di worker yang sama. Jadi bahkan sebelum attacker dapat shell, mereka mungkin sudah dapat password.

5. Semua SAPI Berpotensi Terdampak

Menurut advisory resmi PHP, semua instalasi PHP yang melayani web request berisiko, termasuk PHP-FPM, Apache dengan mod_php, php-cgi, FrankenPHP, dan LiteSpeed. Risiko tertinggi ada di mod_php — untuk kasus CVE-2026-109618, exploit tanpa aplikasi sama sekali sudah terbukti jalan di mod_php. PHP-FPM punya perilaku berbeda (worker langsung dimatikan kalau request gagal di tahap awal setup) sehingga satu jalur exploit tidak langsung bisa dipakai, tapi advisory menegaskan FPM tetap susceptible, dan untuk CVE-2026-109619 eksploitasi RCE sudah tervalidasi di mod_php maupun FPM.

Bedah Teknis: Akar Masalah di Zend Engine

Bagian ini kita bahas agak dalam. Buat yang cuma mau tahu cara patch-nya, silakan lompat ke bagian mitigasi — tapi memahami root cause-nya bikin kita ngerti kenapa bug macam ini bisa lolos lebih dari satu dekade.

Kedua vulnerability hidup di Zend, yaitu implementasi C yang menjadi jantung PHP: yang mengompilasi source PHP ke bytecode, mengeksekusinya di virtual machine, dan mengelola semua yang dibutuhkan bahasa saat runtime — variabel, array, object, reference counting, dan alokasi memori. Zend ini bukan komponen opsional atau add-on pihak ketiga; dia ikut ter-ship di setiap build PHP (makanya source-nya ada di direktori Zend/ di php-src). Bug di Zend = bug di mesin PHP itu sendiri, yang berdampak ke semua aplikasi, framework, dan ekstensi yang berjalan di interpreter tersebut.

Dua mesin Zend yang jadi pusat masalah: HashTable (yang menampung semua array PHP, termasuk superglobal $_POST) dan Zend Memory Manager (Zend MM), allocator khusus per-request yang duduk antara PHP dan sistem operasi.

zend_bailout() dan longjmp(): Jalan Pintas yang Berbahaya

Ketika PHP menghadapi kondisi fatal — memory_limit terlampaui, maximum execution time kelewat, atau koneksi klien terputus — PHP tidak mengembalikan error naik ke call stack seperti bahasa pada umumnya. PHP menaikkan fatal error dan memanggil zend_bailout(), yang melakukan LONGJMP untuk meninggalkan konteks eksekusi saat itu sepenuhnya:

// Zend/zend.c
ZEND_API ZEND_COLD ZEND_NORETURN void _zend_bailout(const char *filename, uint32_t lineno)
{
    ...
    CG(unclean_shutdown) = 1;
    ...
    LONGJMP(*EG(bailout), FAILURE);
}

Intinya: tidak ada kode antara fatal error dan blok zend_catch yang mengelilinginya yang akan dieksekusi. Fungsi C yang sedang di tengah membangun sebuah data structure langsung dibuang begitu saja: destructor tidak jalan, bookkeeping tidak di-rollback, dan tidak ada yang mencatat bahwa struktur tersebut belum lengkap. PHP lalu melanjutkan ke rangkaian cleanup yang mengasumsikan semua struktur dalam keadaan konsisten.

Asumsi itulah yang rusak. Dan di situlah kedua CVE ini hidup.

CVE-2026-109618: Cleanup Membaca Memori yang Belum Terisi

CVE ini mencakup konteks yang meninggalkan memori request dalam keadaan uninitialized. Polanya kira-kira begini:

  1. Sebuah data structure ditandai sudah "memuat" sebuah entry sebelum memori untuk entry tersebut dialokasikan.
  2. Alokasi itulah yang ternyata melewati memory_limit — sehingga terjadi OOM, zend_bailout() dipanggil, dan eksekusi loncat keluar.
  3. Entry tersebut tertinggal menampung stale heap data (sisa memori yang bisa dikontrol attacker).
  4. Routine cleanup request yang gagal itu membaca dan melakukan percabangan (branch) berdasarkan byte-byte tersebut — di sinilah attacker bisa mengarahkan eksekusi.

Strategi untuk memicu OOM-nya sendiri jeli banget. Beberapa masalah parsing multipart/form-data bisa membawa request ke OOM sambil tetap tampak berada dalam limit PHP yang dikonfigurasi:

  • Request multipart tanpa Content-Length yang valid bisa lolos pemeriksaan post_max_size awal dan terus mensuplai data body ter-decode.
  • Sebuah part multipart bisa berisi jumlah header yang tak terbatas. Representasi header-header itu di dalam PHP bisa memakan jauh lebih banyak memori daripada representasi di kabel — jadi request yang "muat" dalam post_max_size tetap bisa menghabiskan memory_limit normal.
  • Empty file controls tidak dihitung ke max_file_uploads, tapi tetap membuat array metadata file seperti biasa. Ditambah nama field yang bersarang (nested) melipatgandakan pekerjaan pembuatan array.

Bug yang mendasari CVE ini — urutan HashTable tertentu — masuk lewat optimasi performa Oktober 2017 dan pertama rilis di PHP 7.3.0. Jalur OOM-nya sendiri lebih tua lagi.

Perbaikannya: patch menghapus longjmp() untuk OOM. Sebagai gantinya, PHP sekarang menunda soft OOM yang graceful sampai titik aman VM berikutnya, plus hard OOM yang langsung _exit() jika konsumsi memori mencapai ambang kedua yang lebih tinggi. Dengan ini, prosedur shutdown tidak akan lagi melihat state yang belum valid.

CVE-2026-109619: State Global yang Tertinggal Antar-Request

CVE ini mencakup konteks yang meninggalkan global state dalam keadaan tidak valid. PHP punya berbagai state global — error, session, object, dan state ekstensi — yang disimpan oleh worker tapi sebenarnya menunjuk ke memori milik satu request. State itu wajib di-reset sebelum memori request dilepas.

Masalahnya, beberapa operasi input, konfigurasi, session, dan error handling berjalan sebelum inisialisasi normal request berikutnya. Operasi-operasi itu tanpa sengaja mengakses state basi yang belum sempat di-reset — dan terjadilah use-after-free.

Untuk exploit-nya butuh dua peran:

  • Producer: operasi PHP yang menyimpan state milik satu request ke lokasi yang bisa diakses PHP nanti di request berikutnya.
  • Consumer: operasi request berikutnya yang membaca, membebaskan, atau bercabang berdasarkan state basi itu sebelum inisialisasi normal meresetnya.

State bisa bertahan karena beberapa sebab: fatal error (termasuk yang disebabkan kehabisan memori) bisa meninggalkan operasi sebelum sempat melakukan reset yang sepadan; bahkan warning non-fatal pun bisa mengisi ulang state error setelah dibersihkan saat shutdown.

Dua consumer yang sudah terkonfirmasi:

  1. Diagnostik INI sebelum inisialisasi request — warning/notice/deprecation saat menerapkan setting INI yang tidak valid atau deprecated sebelum inisialisasi executor biasa. Contohnya: auto_detect_line_endings=1, nilai filter.default yang aneh, setting assert.* legacy, mbstring.http_input, date.timezone yang invalid, dan seterusnya. Penting: menyembunyikan error dengan error_reporting, @, atau mematikan display_errors tidak melindungi — state global diakses sebelum PHP memutuskan mau melaporkan atau tidak.
  2. Session upload progress — fitur yang aktif secara default ini bisa mencapai penanganan session sebelum inisialisasi session normal, sehingga bisa mengonsumsi state session/decoder yang ditinggalkan request yang terputus. Ini yang paling banyak dieksploitasi di serangan in the wild.

Dua kasus yang paling terkonfirmasi: fatal_error_backtraces di PHP 8.5 (saat aktif, pelaporan fatal error menyimpan state backtrace milik request dan reset-nya selalu terlewat saat shutdown) dan lifecycle session upload progress (tanpa perlu session_start() sama sekali!).

Perbaikannya: patch melakukan reset yang lebih luas ke seluruh state terkait request, sehingga tidak ada yang selamat melewati batas request. Untuk PHP 8.5, fatal_error_backtraces juga dibuat lebih aman.

Versi Terdampak dan Versi Aman

Jendela rentannya sudah terbuka lebih dari tujuh tahun di rilis PHP. Tidak ada satu branch yang kebal:

Branch PHPRentanVersi Perbaikan
8.5di bawah 8.5.128.5.12
8.4di bawah 8.4.278.4.27
8.3di bawah 8.3.368.3.36
8.2di bawah 8.2.358.2.35
7.4 – 8.1SemuaTidak ada rilis resmi; tersedia minimal source backport dari tim PHP
5.4 – 7.3SemuaEOL, tidak ada perbaikan dari proyek PHP

Beberapa catatan:

  • Distro Linux dan vendor LTS umumnya menerima patch lebih awal, jadi cek repo paket kamu — kemungkinan besar sudah tersedia.
  • PHP 8.2 akan end of life tanggal 31 Desember 2026 dan tidak akan menerima perbaikan keamanan lagi setelah itu. Kalau masih di 8.2, rencanakan upgrade.
  • Buat yang build dari source atau pakai PHP EOL (7.4–8.1), tim PHP menyediakan branch backport minimal: PHP-7.4-CVE-2026-109618-109619, PHP-8.0-..., dan PHP-8.1-... di repositori php-src.
  • Kalau kamu bergantung pada rpms.remirepo.net (dikelola relawan), PHP menyarankan pindah ke paket distro atau build dari source supaya bisa update segera.

Cara Cek Versi PHP di Server Kamu

Sebelum patch, cek dulu versi yang benar-benar dipakai untuk melayani web request.

Jangan Tertukar: CLI vs FPM vs mod_php

Ini jebakan paling umum! Perintah php -v di terminal menunjukkan versi PHP CLI, yang bisa saja berbeda dengan versi yang dipakai web server. Mengupdate paket CLI saja tidak otomatis mengupdate service PHP-FPM atau modul Apache.

# Versi PHP CLI (belum tentu yang dipakai web!)
php -v
 
# Versi PHP-FPM yang berjalan
php-fpm8.3 -v        # atau php-fpm8.4, tergantung versi
systemctl status php*-fpm
 
# Cek modul PHP yang dipakai Apache
apache2ctl -M | grep php
 
# Cek versi yang dilihat web server — cara paling pasti!
echo "<?php phpinfo();" | sudo tee /var/www/html/info.php
curl -s http://localhost/info.php | grep -i "PHP Version"
sudo rm /var/www/html/info.php

Cek Paket Terpasang (Debian/Ubuntu)

dpkg -l | grep -i php | awk '{print $2, $3}'

Cek Paket Terpasang (RHEL/Fedora)

rpm -qa | grep -i php

Cara Patch

Debian / Ubuntu

sudo apt update
sudo apt install --only-upgrade php* -y
 
# Restart SEMUA service PHP yang mungkin jalan
sudo systemctl restart apache2          # kalau pakai mod_php
sudo systemctl restart php8.3-fpm       # sesuaikan versi
sudo systemctl restart nginx
 
# Verifikasi
php-fpm8.3 -v

RHEL / Fedora / Rocky / AlmaLinux

sudo dnf update php* -y
sudo systemctl restart httpd            # atau php-fpm / nginx

Build dari Source

Unduh source terbaru dari php.net/downloads dan build ulang. Untuk PHP EOL 7.4–8.1, pakai branch backport PHP-X.Y-CVE-2026-109618-109619 dari repositori php-src.

Setelah Patch

  1. Restart semua worker — patch tidak bekerja untuk proses yang masih berjalan dengan binary lama.
  2. Verifikasi lewat phpinfo() dari sisi web, bukan dari CLI.
  3. Kalau menjalankan banyak server/container, jangan lupa image Docker yang pakai base PHP — rebuild image-nya.

Mitigasi Sementara (Kalau Belum Bisa Update)

Peringatan keras: dari advisory resmi PHP sendiri — "There are no complete mitigations, updating is the only safe choice." Semua langkah di bawah ini hanya mengurangi paparan jalur serangan tertentu, bukan menutup semuanya. Perlakukan ini sebagai jembatan, bukan solusi.

Untuk CVE-2026-109618 (OOM corruption)

; Set di php_admin_value (FPM pool / Apache config) supaya aplikasi tidak bisa override
memory_limit = -1
 
; Jaga post_max_size tetap rendah
post_max_size = 8M          ; kalau aplikasi tidak butuh upload file
; post_max_size = 32M       ; kalau butuh upload file
upload_max_filesize = 4M    ; harus lebih kecil dari post_max_size
 
; Kurangi kedalaman nesting input
max_input_nesting_level = 32

Detail penting:

  • Set memory_limit=-1 secara administratif (pakai php_admin_value di pool FPM atau konfigurasi Apache), lalu cek ulang tidak ada pool/direktori/aplikasi yang mengembalikan limit finit. Ini menghilangkan kegagalan limit memori PHP yang bisa dikontrol attacker — tapi kegagalan alokasi dari level yang lebih bawah masih bisa mencapai jalur rentan.
  • Terapkan limit di level web server/proxy untuk: ukuran request ter-decode, jumlah field input, jumlah part multipart, jumlah header per part, dan kedalaman nesting. Limit ini juga harus mencakup request tanpa Content-Length yang valid.
  • Kalau aplikasi tidak pakai multipart form data sama sekali, blokir request begitu di frontend sebelum sampai ke PHP.
  • Batas memori container/cgroup (memory.max) bisa dipakai sebagai pagar ketersediaan, idealnya dengan kebijakan yang hanya mematikan worker yang kena — misalnya tiap worker punya group sendiri.
  • JANGAN pakai RLIMIT_AS atau RLIMIT_DATA sebagai pengganti! PHP secara eksplisit memperingatkan bahwa ini justru memicu kegagalan alokasi di jalur yang rentan.

Untuk CVE-2026-109619 (stale global state)

; Matikan session upload progress (aktif default!)
session.upload_progress.enabled = 0
 
; Khusus PHP 8.5
fatal_error_backtraces = 0

Detail penting:

  • Set di php.ini, FPM pool, atau konfigurasi server yang diterapkan sebelum parsing request. Jangan andalkan ini_set() atau .user.ini — itu terlambat. Setelah set, restart semua worker.
  • Ini memblokir jalur session yang sudah terkonfirmasi, tapi tidak semua varian. Advisory secara eksplisit menyatakan tidak ada mitigasi konfigurasi yang menutupi setiap operasi.
  • Bersihkan setting INI invalid/deprecated yang diterapkan per-request dan memicu diagnostik sebelum inisialisasi. Menyembunyikan diagnostik dengan error_reporting, display_errors, atau @ tidak membantu.
  • Perbaiki fatal error dan timeout yang bisa dicapai attacker, termasuk kegagalan di callback, pemrosesan upload/import, dan cleanup.
  • Kalau performa bukan masalah, pertimbangkan pm.max_requests=1 di FPM untuk memutus siklus producer-consumer antar-request.
  • Fitur session upload progress sendiri nyaris tidak pernah dipakai dan minim pengujian — pertimbangkan untuk tetap mematikannya meski sudah patch.

Deteksi Serangan dan Hardening WAF

Apa yang Bisa Dilihat di Log

Serangan PHP2Shell memang senyap, tapi advisory menganjurkan audit terisolasi dengan log_errors=On, error_log yang berfungsi, dan error_reporting=E_ALL di konfigurasi startup, lalu tinjau log Apache, PHP-FPM, reverse proxy, dan service untuk:

  • Warning/deprecation/core error yang berulang sebelum script target jalan.
  • Warning yang muncul saat cleanup ekstensi/server (setelah state error normal dibersihkan).
  • Fatal, parse, dan uncaught error.
  • Maximum execution time exceeded yang bisa diprediksi.
  • Request multipart/form-data mencurigakan dengan field PHP_SESSION_UPLOAD_PROGRESS, jumlah header yang tak wajar dalam satu part, atau puluhan field file kosong dalam satu request.

Catatan jujur: ketiadaan error di log bukan bukti aman. Log historis mungkin dikumpulkan tanpa severity deprecation, dan kegagalan bisa terjadi sebelum PHP sempat menulis pesan. Log melengkapi audit konfigurasi statis — bukan penggantinya.

WAF Rules

  • Cloudflare sudah menyalakan mitigasi default untuk semua pelanggan (termasuk gratis) sejak sebelum patch rilis, dan terus memperbarui rules saat vector baru muncul.
  • AWS WAF: AWS menerbitkan panduan rules yang fokus ke traffic multipart, ukuran request body, dan field session upload progress.
  • Buat yang self-hosted WAF (ModSecurity, dsb.): batasi ukuran body, jumlah part, jumlah header per part, dan blokir request tanpa Content-Length yang valid untuk endpoint yang menerima form upload.

Pelajaran Penting

1. Bug bisa tidur lebih dari satu dekade. Jalur kode yang paling tua di sini (session path) berasal dari PHP 5.4 (2012). Setiap versi PHP yang dirilis dalam 10+ tahun terakhir membawa bug ini. Ini pengingat bahwa kode "lama dan stabil" bukan berarti bebas cacat — bisa jadi cuma belum ketahuan.

2. Keamanan aplikasi tidak cukup. Kita terbiasa audit kode aplikasi, tapi runtime di bawahnya jarang disentuh. PHP2Shell membuktikan: aplikasi yang dirawat sempurna punya paparan yang sama persis dengan yang ditinggalkan. Defense in depth harus mencakup patching runtime, bukan cuma kode.

3. AI ikut berperan dalam menemukan bug kelas ini. Wiz dan Calif sama-sama mengonfirmasi memakai model AI dalam risetnya, dan tim Gemini membantu proses perbaikan. Ini era baru: bug memori C kelas berat yang butuh analisis manual berbulan-bulan kini bisa digali dengan bantuan AI — baik untuk pertahanan maupun serangan.

4. Proses disclosure bisa berantakan, dan itu harus diantisipasi. Kebocoran di Hacker News memaksa rilis dipercepat sehari. Tim PHP merespons dengan baik (advance notice + rilis lebih cepat), tapi jelas: ekosistem harus siap untuk skenario "n-day dalam hitungan jam".

5. Hanya update yang menyelesaikan masalah. Sekali lagi, dari mulut tim PHP sendiri: tidak ada mitigasi konfigurasi yang lengkap. session.upload_progress.enabled=0 memblokir jalur yang sudah dikonfirmasi tapi bukan semua varian; memory_limit=-1 menghilangkan trigger OOM yang bisa dikontrol tapi bukan semua kemungkinan kegagalan alokasi. Patch, restart, verifikasi.

Kesimpulan

PHP2Shell (CVE-2026-109618 dan CVE-2026-109619) adalah pengingat keras bahwa ancaman bisa datang dari lapisan yang paling kita percaya — bahasa pemrograman itu sendiri. Dengan satu request POST anonim, attacker bisa menjalankan perintah di server, membaca memori berisi rahasia, dan meninggalkan jejak yang nyaris nol.

Untungnya, perbaikannya sudah tersedia dan gratis. Daftar tindakan kamu hari ini:

  1. Cek versi PHP yang dipakai web server (bukan CLI!) — lewat phpinfo() dari sisi web.
  2. Update ke 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 (atau paket distro yang sudah di-backport) sesegera mungkin.
  3. Restart semua worker dan verifikasi lagi versinya.
  4. Kalau belum bisa update, terapkan mitigasi sementara di atas — sambil mempercepat jadwal update.
  5. Periksa log untuk tanda-tanda percobaan eksploitasi, dan pastikan WAF kamu aktif.

Jangan menunda untuk yang ini. Bug yang sudah bersembunyi 10 tahun ini sekarang sedang aktif dieksploitasi secara masif di internet. Patch hari ini juga.

FAQ Singkat

Saya pakai shared hosting, apa yang harus saya lakukan? Kabar baiknya: ini urusan provider hosting, bukan kamu. Kabar buruknya: kamu tidak bisa memaksa mereka cepat. Kirim tiket ke support mereka dengan dua CVE ini dan tanyakan kapan PHP di server kamu di-update ke versi yang aman. Sementara itu, pastikan WAF di depan situs kamu aktif (misalnya lewat Cloudflare) dan pantau pengumuman dari provider.

Apakah cukup pasang WAF saja tanpa update? Tidak. WAF adalah pagar tambahan, bukan pintu yang terkunci. Cloudflare sendiri melaporkan attacker terus mengganti payload untuk menembus rules mereka. WAF membeli waktu; patch yang menyelesaikan masalah. Advisory PHP secara eksplisit menyatakan hanya update yang merupakan mitigasi lengkap.

Saya masih di PHP 7.4 / 8.0 / 8.1, bagaimana? Versi-versi ini sudah EOL dan tidak akan menerima rilis resmi. Tim PHP menyediakan branch backport source minimal (PHP-7.4-CVE-2026-109618-109619, dst.) untuk yang build dari source. Beberapa distro dan vendor LTS juga menyediakan backport di paket mereka — cek dengan vendor kamu. Kalau tidak ada opsi itu, inilah saatnya merencanakan upgrade ke branch yang didukung (8.2.35 ke atas, tapi ingat 8.2 EOL akhir Desember 2026 — idealnya langsung ke 8.3/8.4/8.5).

Apakah PHP CLI di server saya juga rentan? Eksploitasinya menargetkan SAPI yang melayani web request (mod_php, FPM, php-cgi, FrankenPHP, LiteSpeed). PHP CLI tidak melayani request web, tapi tetap sebaiknya ikut di-update supaya seluruh instalasi konsisten — dan ingat, paket CLI dan service FPM sering ter-update terpisah.

Saya pakai Laravel / Symfony / WordPress, apakah aman karena framework-nya sudah di-patch? Tidak relevan. Bug-nya ada di interpreter PHP, bukan di framework. Framework mana pun yang berjalan di PHP rentan punya paparan yang sama. Yang menentukan adalah versi PHP binary-nya, bukan versi framework-nya.

Bagaimana cara tahu apakah server saya sudah pernah dieksploitasi? Sulit, karena serangannya dirancang senyap. Yang bisa dilakukan: audit log web server dan PHP-FPM untuk request POST multipart yang mencurigakan (apalagi yang membawa field PHP_SESSION_UPLOAD_PROGRESS), periksa proses mencurigakan yang berjalan sebagai user web server, cek file yang berubah di direktori web root, dan audit kredensial yang pernah lewat di server tersebut (rotasi password/API key adalah langkah yang wajar setelah insiden). Kalau ragu, libatkan tim incident response.

Kenapa memory_limit=-1 justru terdengar seperti ide yang buruk? Secara intuitif memang terdengar aneh — mematikan limit memori kan justru membuka pintu DoS? Tapi di konteks ini, limit memori yang finit adalah trigger yang bisa dikontrol attacker untuk mencapai jalur bug OOM. Dengan memory_limit=-1 (yang diterapkan secara administratif), attacker kehilangan tombol picu yang bisa diprediksi itu. Risiko DoS-nya di-manage lewat limit lain: post_max_size yang rendah, limit jumlah part/field/header di frontend, dan pagar cgroup/container. Setelah patch terpasang, kamu bebas menyesuaikan limit ini kembali sesuai kebutuhan.

Apakah cukup update paket php di apt/dnf, selesai? Belum tentu. Pastikan SEMUA service yang menjalankan PHP ikut di-update dan di-restart: modul Apache (libapache2-mod-php*), PHP-FPM (php*-fpm), dan jangan lupa container/image Docker yang memakai base PHP. Verifikasi akhirnya tetap sama: buka phpinfo() dari sisi web dan cek versinya.

Referensi

Tulisan lain