Sebuah penemuan keamanan kritis baru saja mengguncang komunitas riset keamanan siber global. Peneliti dari Verichains bernama y198 berhasil membuktikan bahwa dua bug yang secara individual sulit dieksploitasi dapat digabungkan menjadi sebuah serangan Remote Code Execution (RCE) yang beroperasi tanpa autentikasi dan tanpa harus mengalahkan mekanisme Address Space Layout Randomization (ASLR). Target serangannya adalah nginx versi 1.30.0, salah satu web server paling banyak digunakan di dunia yang menguasai pasar lebih dari 30% dari seluruh situs web publik. Temuan ini tidak hanya membuktikan kelemahan spesifik pada nginx, tetapi juga memperkenalkan teknik partial overwrite 2 byte yang bisa menjadi model serangan baru untuk kelas kerentanan serupa.
Penelitian ini dipublikasikan pada tanggal 6 Juni 2026 dengan judul “Two Bytes to RCE: Chaining Rift + PoolSlip” dan disertai dengan kode Proof-of-Concept (PoC) lengkap yang tersedia di GitHub. Yang membuat penemuan ini sangat mengkhawatirkan adalah tingkat keberhasilannya yang mencapai 90% dalam environment Docker pada Debian 13 dengan glibc 2.41. Dalam dunia eksploitasi keamanan, angka reliability sebesar ini menunjukkan bahwa serangan ini bukan sekadar konsep teoretis, melainkan operationally viable yang bisa digunakan dalam skenario serangan nyata oleh aktor jahat yang memiliki kemampuan teknis memadai.
Apa yang Terjadi? Dua CVE yang Mengancam nginx
Serangan ini memanfaatkan dua CVE yang berbeda namun saling melengkapi. CVE pertama adalah CVE-2026-42945 yang diberi nama kode “Rift”. Rift adalah sebuah forward heap overflow yang terjadi di dalam mesin rewrite engine nginx. Kerentanan ini terpicu ketika sebuah aturan rewrite menghasilkan URI yang mengandung tanda tanya (?) literal sebagai pemisah query string. Ketika nginx memproses aturan rewrite semacam ini, terjadi ketidakcocokan pada flag is_args yang menyebabkan query string yang ditangkap disalin ke buffer URI utama alih-alih ke buffer args. Masalahnya, buffer URI utama memiliki alokasi ukuran tetap yang sudah terisi, sehingga data yang disalin melampaui kapasitas yang dialokasikan dan menyebabkan overflow ke area memori di sebelahnya.
CVE kedua adalah CVE-2026-9256 yang diberi nama “PoolSlip”. PoolSlip adalah sebuah heap over-read yang terjadi di path rewrite yang berbeda. Dalam kerentanan ini, variabel $args memiliki ketidaksesuaian akuntansi panjang yang menyebabkan nilai yang dikembalikan jauh lebih besar dari query string yang sebenarnya. Akibatnya, nginx memasukkan byte mentah dari heap ke dalam nilai $args yang direfleksikan, sehingga mengekspos nilai pointer mentah dari area memori yang dialokasikan di dekat request pool. Kerentanan ini sendiri tidak melakukan kerusakan memori, tetapi ia membocorkan informasi kritis tentang layout memori sistem.
Kenapa Kedua Bug Ini Harus Digabungkan?
Secara individual, kedua bug ini sulit dieksploitasi secara efektif. Rift memerlukan penulisan pointer 8-byte penuh ke lokasi heap yang berguna, namun setiap byte yang ditulis harus URL-safe. Hanya 79 dari 256 kemungkinan nilai byte yang dianggap URL-safe, yang berarti probabilitas sebuah alamat heap acak memiliki semua 8 byte URL-safe adalah sangat kecil. Perhitungan menunjukkan probabilitasnya hanya sekitar 0.09%. Monte-Carlo sampling dengan 2.000.000 sampel di atas entropi ASLR 34-bit sistem pengujian mengkonfirmasi bahwa strategi penulisan penuh ini bukan pendekatan yang bisa diandalkan.
PoolSlip di sisi lain hanya melakukan pembacaan dan tidak memberikan primitive penulisan apapun. Ia bisa mengekspos alamat heap dan libc, tetapi sendirian tidak bisa menjalankan kode jahat. Namun, ketika digabungkan, kedua bug ini menjadi sangat mematikan. PoolSlip berfungsi sebagai primitive info leak yang memungkinkan penyerang mendapatkan alamat heap_base dan libc_base hanya dalam satu request GET, sementara Rift menyediakan primitive penulisan yang memungkinkan manipulasi pointer di heap. Dengan mengetahui alamat heap secara tepat, penyerang hanya perlu melakukan partial overwrite 2 byte terendah dari pointer yang sudah ada, bukan menulis 8 byte penuh. Probabilitas keberhasilan 2 byte URL-safe jauh lebih tinggi, dan teknik ini sepenuhnya independen terhadap ASLR karena byte tinggi pointer tidak diubah.
Detil Teknis: Mekanisme Serangan Lengkap
Alur serangan lengkap dimulai dengan tahapan warm-up yang terdiri dari sekitar 40 request GET ke path /search/+ x 300. Tujuan tahapan ini adalah menstabilkan layout heap sehingga pointer libpcre pada offset 1729 dari $args yang membengkak berada pada posisi yang stabil dan dapat diandalkan. Tanpa warm-up yang memadai, offset pointer bisa bervariasi antar sesi serangan, menyebabkan kegagalan eksploitasi. Ini adalah pola yang umum dijumpai dalam exploitasi heap bertahapan (multi-stage heap exploits) di mana kondisi memori harus diprediksi secara konsisten sebelum primitive penulisan dilakukan.
Setelah heap stabil, tahapan leak dilakukan dengan mengirim satu request GET yang memanfaatkan PoolSlip. Request ini menyebabkan variabel $args membengkak dan mengekspos data mentah dari heap dalam respons error 503. Pada offset byte 1489 dari $args yang membengkak, terdapat pointer heap yang memungkinkan perhitungan heap_base. Pada offset 1729, terdapat pointer ke area cluster heap libpcre/regex yang berada pada offset negatif tetap dari libc_base (yaitu -0xb0ad08). Kedua alamat ini diekstraksi dalam satu request, memberikan penyerang peta lengkap layout memori target.
Tahapan ketiga adalah heap spray yang menggunakan 8 POST request ke /api/upload yang ditahan (held). POST pertama (#0) berisi command string yang akan dieksekusi, sementara POST lainnya berisi data “tiled record” yang dirancang untuk menempatkan entri ngx_pool_cleanup_t palsu di posisi yang dapat diprediksi di heap. Entri palsu ini memiliki field handler yang diatur ke alamat fungsi system() dan field data yang menunjuk ke command string. Spray ini memastikan bahwa ada rekaman terkontrol di heap yang siap menjadi target penulisan.
Tahapan groom kemudian membuka 16 koneksi TCP kosong dan menutupnya tepat sebelum koneksi korban terhubung. Tujuannya adalah menciptakan “lubang” di heap yang akan diisi oleh alokasi bersih dari koneksi korban. Koneksi korban dikirim sebagai POST request yang ditahan ke /api/upload dengan body tiled. Request ini mendapatkan alokasi limit_conn cleanup yang pointer-nya berada di posisi yang dapat diprediksi berdasarkan heap_base yang sudah diketahui. Setelah korban terhubung, 24 spray tambahan dikirim untuk menempatkan lebih banyak rekaman di atas pointer cleanup.
Tahapan terakhir adalah memicu Rift dengan menyelesaikan request yang ditahan. Ketika request ditulis ulang oleh nginx, flag is_args mismatch menyebabkan overflow yang menulis 2 byte terendah dari YYYY ke posisi offset +0x40 dari pool korban, yaitu lokasi field cleanup. Overwrite ini mengubah pointer cleanup sehingga menunjuk ke salah satu tiled record yang sudah disiapkan oleh spray. Ketika koneksi korban ditutup, nginx memanggil ngx_http_free_request yang kemudian memanggil ngx_destroy_pool. Fungsi ini berjalan melalui linked list cleanup dan memanggil handler(data) untuk setiap entri. Karena cleanup sekarang menunjuk ke entri palsu, pemanggilan yang terjadi adalah system("perintah_jahat"), yang menjalankan perintah shell di context worker nginx.
Alasan Teknik Partial Overwrite Sangat Efektif
Teknik partial overwrite 2 byte yang digunakan dalam eksploitasi ini layak mendapatkan perhatian khusus karena ia memecahkan salah satu tantangan terbesar dalam eksploitasi heap modern: bagaimana menulis ke lokasi yang tepat ketika seluruh alamat memori dirandomisasi oleh ASLR. Dalam pendekatan konvensional, penyerang harus menulis pointer penuh 8 byte (atau 6 byte pada sistem 32-bit) ke lokasi yang sudah diketahui. Namun dengan ASLR, setiap byte dari alamat tersebut bisa berubah antar sesi, dan constrait URL-safe membatasi hanya 31% nilai byte yang bisa digunakan. Kombinasi dari randomisasi alamat dan constrait karakter membuat penulisan penuh hampir mustahil secara statistik.
Partial overwrite menghindari masalah ini dengan hanya mengubah 2 byte terendah dari pointer yang sudah ada di heap. Byte tinggi (yang mengandung informasi region memori) tetap utuh dan tidak diubah. Ini berarti penyerang tidak perlu mengetahui byte tinggi dari alamat target secara persis; ia hanya perlu memastikan bahwa 2 byte terendah, ketika dikombinasikan dengan byte tinggi yang sudah ada, akan menunjuk ke rekaman yang sudah disiapkan oleh spray. Karena penyerang mengontrol isi spray, ia bisa memilih posisi rekaman sehingga 2 byte terendah dari alamatnya selalu URL-safe. Ini mengubah masalah probabilistik menjadi masalah deterministik, meningkatkan keberhasilan dari kurang dari 1% menjadi sekitar 90%.
Mekanisme Cleanup Callback yang Dieksploitasi
Untuk memahami mengapa eksploitasi ini bisa mencapai eksekusi kode, perlu dipahami bagaimana nginx mengelola memory pool-nya. nginx menggunakan sistem memory pool yang disebut ngx_pool_t untuk mengelola alokasi memori per-request. Setiap pool memiliki linked list dari cleanup handlers yang direpresentasikan oleh struktur ngx_pool_cleanup_t. Struktur ini berisi tiga field: handler (pointer ke fungsi callback), data (argument yang diteruskan ke callback), dan next (pointer ke cleanup berikutnya dalam list).
Ketika request selesai diproses dan koneksi ditutup, nginx memanggil ngx_destroy_pool yang berjalan melalui seluruh cleanup list dan memanggil handler(data) untuk setiap entri. Ini adalah mekanisme yang sah dan diperlukan untuk membersihkan resource seperti file descriptor, koneksi database, atau buffer yang dialokasikan selama lifecycle request. Namun, jika field handler dan data bisa dimanipulasi oleh penyerang, mekanisme ini menjadi primitive eksekusi kode yang sangat bersih: tidak perlu shellcode, tidak perlu ROP chain, cukup kendalikan dua pointer dan trigger pool destruction.
Perbedaan Layout Heap antar Distribusi Linux
Salah satu temuan penting dari penelitian ini adalah perbedaan signifikan dalam layout heap antara Debian 13 dan Ubuntu pada glibc 2.41. Di Ubuntu, teknik mmap untuk menempatkan body POST besar di bawah libc bekerja dengan baik, memungkinkan leak alamat libc secara langsung. Namun di Debian 13, alokasi besar mendarat di cluster brk/PIE alih-alih di bawah libc. Perbedaan ini berarti offset yang diderivasikan di satu distribusi tidak bisa langsung ditransfer ke distribusi lain.
Solusi yang ditemukan oleh peneliti adalah menggunakan pointer libpcre pada offset 1729 dari $args yang membengkak. Pointer ini berada pada offset negatif tetap -0xb0ad08 dari libc_base di Debian 13, menjadikannya primitive leak yang portabel untuk distribusi ini. Pelajaran penting dari temuan ini adalah bahwa eksploitasi heap modern sangat bergantung pada kondisi spesifik dari runtime target. Peneliti keamanan harus menyesuaikan offset dan teknik untuk setiap distribusi, versi glibc, dan konfigurasi kernel yang berbeda.
Dampak terhadap Ekosistem nginx Global
nginx adalah salah satu web server paling banyak digunakan di dunia, dipakai sebagai reverse proxy, load balancer, dan web server di jutaan situs web. Di Indonesia sendiri, nginx digunakan secara luas oleh penyedia hosting, perusahaan teknologi, instansi pemerintah, dan berbagai layanan digital lainnya. Banyak dari部署 ini menggunakan aturan rewrite yang kompleks untuk URL management, yang berarti potensi paparan terhadap kerentanan ini cukup tinggi. Terutama bagi organisasi yang menjalankan nginx 1.30.0 dengan konfigurasi rewrite yang melibatkan variabel user input, risiko serangan ini nyata dan harus segera dievaluasi.
Yang perlu diperhatikan adalah bahwa serangan ini tidak memerlukan autentikasi apapun — penyerang hanya perlu akses jaringan ke port 80 atau 443 nginx target. Dalam konteks infrastruktur Indonesia di mana banyak layanan publik berbasis web diakses dari internet, ini berarti setiap nginx yang rentan bisa menjadi target serangan. Dampaknya bisa berupa eksekusi kode jahat dengan privilege worker process nginx, yang memungkinkan penyerang membaca file sensitif, memasang backdoor, atau menjadikan server sebagai pivot untuk serangan lateral ke jaringan internal.
Analisa Retasan
Penemuan ini menunjukkan tren yang sangat mengkhawatirkan dalam dunia keamanan siber: bug yang secara individual dianggap “sulit dieksploitasi” ternyata bisa digabungkan menjadi serangan yang sangat reliable. Teknik chaining ini bukan hal baru, namun kombinasi antara info leak yang presisi dengan partial overwrite yang deterministik menetapkan standar baru untuk apa yang mungkin dilakukan terhadap software populer seperti nginx.
Yang paling mengkhawatirkan dari perspektif pertahanan adalah bahwa teknik partial overwrite 2 byte ini mengatasi ASLR tanpa teknik canggih — cukup dengan mengubah 2 byte terendah pointer yang sudah ada. ASLR selama ini dianggap sebagai salah satu pertahanan utama terhadap serangan memory corruption, namun temuan ini membuktikan bahwa dengan primitive leak yang memadai, ASLR bisa diakali dengan cara yang elegan dan efisien. Ini bukan berarti ASLR tidak berguna, tetapi organisations harus memahami keterbatasannya dan tidak mengandalkannya sebagai satu-satunya lapisan pertahanan.
Bagi tim DevOps dan keamanan di Indonesia, langkah pertama yang harus segera dilakukan adalah melakukan audit pada semua konfigurasi rewrite nginx yang berjalan di lingkungan produksi. Periksa apakah ada aturan rewrite yang mengandung tanda tanya literal (
?) diikuti dengan variabel yang menyalin input pengguna ke buffer URI utama. Selain itu, pastikan nginx selalu di-update ke versi terbaru yang sudah mengandung patch untuk CVE-2026-42945 dan CVE-2026-9256. Jangan pernah menganggap bug yang terlihat “kecil” — over-read atau overflow yang tampak tidak berbahaya bisa menjadi komponen kunci dalam rantai serangan yang mematikan.
Sumber: core-jmp.org – Two Bytes to RCE | PoC: GitHub PoC | Penulis: y198, Verichains

