flawopen.com/Teardowns/cve-2026-87902-wordpress-page-template-path-traversal
CVE-2026-87902: Path traversal pada template halaman WordPress
Nama halaman hasil dekode yang tidak divalidasi masuk ke resolusi template, sehingga PHP lokal dapat disertakan tanpa autentikasi. RCE memerlukan kondisi tema dan PHP tertentu.[1]
Bayangkan pustakawan yang memeriksa permintaan sebelum mengambil buku. WordPress memeriksa satu jalur ke daftar template, tetapi melewatkan jalur dari nama yang sudah didekode. Penanda khusus dapat membawanya keluar dari direktori tema. Perbaikan memvalidasi nama dan menjaga template dalam direktori yang diizinkan.[1], [2], [3]
Konsep Kunci & Istilah
Resolusi template halaman- WordPress mengurutkan kandidat PHP dan mencari file pertama yang cocok di tema aktif.[1], [2]
Path traversal- Komponen seperti
..dapat keluar dari direktori tujuan jika input tidak divalidasi.[1] Penyertaan PHP lokal- Memuat file PHP yang sudah ada di server; RCE memerlukan kondisi tambahan.[1]
`validate_file()`- Fungsi WordPress yang menolak komponen jalur terlarang sebelum digunakan.[3]
Pemetaan kerangka kerja
- Referensi CWE untuk kelemahan yang dijelaskan dalam panduan ini: CWE-98
- CISA KEV — ditambahkan 2026-09-25 — CVE-2026-87902
Analisis Akar Masalah (Root Cause)
Di get_page_template(), WordPress mendekode pagename lalu menambahkan page-{name}.php tanpa validate_file(), sementara cabang di sebelahnya melakukan pemeriksaan tersebut. Jalur dapat keluar dari tema. Diperlukan direktori tingkat atas page-* dan PHP lokal yang dapat dibaca; RCE juga memerlukan kondisi PHP/server tambahan. Versi 7.1.2 memvalidasi nilai hasil dekode dan membatasi jalur di locate_template(). Advisori WordPress mengklasifikasikan kelemahan ini sebagai CWE-98 (pengendalian nama berkas yang tidak tepat pada PHP include/require) dan mencantumkan Robert Ressl sebagai penemu serta pihak yang mengungkapkannya secara bertanggung jawab.[1], [2], [3], [7]
Cakupan CVE-2026-87902: kondisi paparan dan RCE bersyarat
| Kondisi deployment | Hal yang dibuktikan sumber primer | Tindakan operator |
|---|---|---|
| Cabang WordPress Core yang terdampak | GHSA mencantumkan versi terdampak per cabang, dari 4.7.0–4.7.36 hingga 7.1.0–7.1.1. Versi perbaikannya berkisar dari 4.7.37 (backport paling awal) hingga 7.1.2 (cabang saat ini); setiap cabang yang tercantum memiliki rilis perbaikan tersendiri. | Periksa versi Core yang terpasang dan terapkan perbaikan untuk cabang tersebut. Tingkatkan versi sebelum 4.7 ke rilis yang masih didukung. |
| Struktur tema aktif | Tema parent atau child yang aktif harus memiliki direktori tingkat teratas dengan nama yang diawali page- (misalnya page-templates). | Periksa direktori kedua tema aktif. Periksa ulang kondisi ini saat tema aktif berubah. |
| Berkas PHP lokal yang dapat dibaca | Berkas .php yang dipilih harus ada di luar direktori tema aktif dan dapat dibaca oleh akun server web. | Periksa berkas PHP lokal yang dapat dibaca server web; rentang versi CVE saja tidak membuktikan bahwa berkas telah disertakan. |
| Lingkungan RCE bersyarat | Advisory menjelaskan RCE hanya jika syarat PHP/server tambahan terpenuhi. Contohnya pearcmd.php saat register_argc_argv=On, image PHP Docker resmi, dan konfigurasi default cPanel dengan PHP sebelum 8.5. | Nilai runtime dan konfigurasi PHP yang sebenarnya. Versi WordPress yang terdampak saja tidak membuktikan RCE atau kompromi. |
Alur Serangan Langkah demi Langkah
Input masuk ke pemilihan template
Permintaan tanpa autentikasi menyediakan nama untuk membuat kandidat; akun dan klik tidak diperlukan.[1]
Pencarian keluar dari akar
Dengan direktori page-* dan PHP lokal yang dapat dibaca, tema dapat menyelesaikan file di luar direktorinya.[1]
Dampak bersyarat
RCE membutuhkan kondisi PHP/server tambahan; versi saja tidak membuktikan eksploitabilitas atau kompromi.[1]
Kode Sumber: Rentan vs Aman
Cuplikan ini membandingkan tag sumber resmi 7.1.1 dan 7.1.2. Patch memvalidasi nilai setelah dekode; rilis yang sama juga membatasi jalur hasil resolusi di locate_template(). Ini perubahan sumber upstream, bukan patch mandiri lengkap atau demonstrasi eksploitasi.[2], [3]
Cuplikan sumber: wp-includes/template.php — get_page_template()
if ( $pagename ) {
$pagename_decoded = urldecode( $pagename );
if ( $pagename_decoded !== $pagename ) {
$templates[] = "page-{$pagename_decoded}.php";
}
}
if ( $pagename ) {
$pagename_decoded = urldecode( $pagename );
if ( $pagename_decoded !== $pagename && 0 === validate_file( $pagename_decoded ) ) {
$templates[] = "page-{$pagename_decoded}.php";
}
}
Daftar Periksa Penguatan Sistem Rekayasa
- ✓Perbarui ke rilis yang diperbaiki untuk cabang Anda dan verifikasi kode yang benar-benar berjalan.[1], [4]
- ✓Inventarisasi WordPress yang terbuka ke Internet dan temukan versi usang sebelum 4.7.[1], [4]
- ✓Jika terekspos sebelum patch, periksa log serta file PHP atau akun tak terduga; sinyal adalah petunjuk investigasi, bukan bukti tunggal.
- ✓Pada resolver sendiri, validasi komponen setelah dekode dan batasi jalur nyata kanonis ke direktori yang diizinkan.[1], [3]
- ✓Pertahankan Core dan tema pada rilis yang didukung; pergantian tema dapat mengubah kondisi paparan.[1], [4]