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

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

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

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

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

Категории

Все категории
Loading categories
cve-2010-4221-lab — От патча к RCE: собственноручно собранный эксплойт для CVE-2010-4221 (переполнение стека TELNET IAC в ProFTPD), с полным описанием пути, продиктованного ошибками | Kitploit
Инструменты/GitHubGitHub/diegslva/cve-2010-4221-lab
Фреймворки для эксплойтовАнализ уязвимостейЭксплуатацияОбратная инженерияТестирование на ПроникновениеОбучение и ОбразованиеЭксплуатация Бинарных ФайловЛаборатории и Практика
GitHubdiegslva/cve-2010-4221-lab

cve-2010-4221-lab

От патча к RCE: собственноручно собранный эксплойт для CVE-2010-4221 (переполнение стека TELNET IAC в ProFTPD), с полным описанием пути, продиктованного ошибками

291 месяц назадЕщё не проверено
Репозиторий

Популярное

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

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

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

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

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

CVE-2010-4221 — Переполнение стека TELNET IAC в ProFTPD: от патча до RCE

Полностью воспроизводимый лабораторный стенд и написанный вручную эксплойт на сырых сокетах для CVE-2010-4221 — переполнение стекового буфера до аутентификации в pr_netio_telnet_gets() ProFTPD — созданный как учебное упражнение по исследованию уязвимостей и разработке эксплойтов.

Каждая неудача задокументирована. Прямой путь — ложь; обходные пути — и есть урок.


Правовое и этическое уведомление — прочтите сначала

Этот репозиторий — учебный артефакт. Он существует, чтобы люди, которые не могут позволить себе наставника или обучение, могли узнать, как на самом деле рождается эксплойт повреждения памяти: от патча, через неудачи, до работающего подтверждения концепции в лаборатории, которой вы владеете.

Работа Red Team — настоящая, профессиональная наступательная безопасность — определяется одним словом: авторизация. Всё, что делает профессионал, происходит в рамках письменного соглашения: подписанного документа о правилах взаимодействия, в котором указаны объём, цели, разрешённые техники, временное окно и люди, которые это одобрили. Без этого документа те же самые нажатия клавиш — это не профессия, а преступление практически в любой юрисдикции на Земле.

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

  • Запускайте это только против прилагаемой Docker-лаборатории или систем, которыми вы владеете.
  • Никогда не запускайте против чего-либо без явного письменного разрешения.
  • Если вы учитесь: добро пожаловать, это создано для вас.
  • Если вы ищете оружие для использования против других: закройте эту вкладку. Эта ошибка из 2010 года; она не принесёт вам ничего, кроме судимости.

Ремесло стоит того, чтобы его изучать. Ремесло чего-то стоит только с дисциплиной, которая приходит вместе с ним.


Уязвимость

ProFTPD обрабатывает TELNET escape-последовательности на управляющем канале FTP. В TELNET байт 0xFF (IAC, «Interpret As Command») является escape-байтом; литеральный 0xFF передаётся как 0xFF 0xFF.

pr_netio_telnet_gets() копирует байты клиента в стековый буфер (char buf[PR_DEFAULT_CMD_BUFSZ+1] из pr_cmd_read, 4104 байта при MAXPATHLEN=4096 в glibc), отслеживая оставшееся место в buflen — переменной типа size_t, беззнаковой.

Уязвимый путь (1.3.3a, netio.c):

case TELNET_IAC:
  switch (cp) {
    ...
    default:
      *bp++ = TELNET_IAC;   // запись №1
      buflen--;             // уменьшение №1
      telnet_mode = 0;
      break;
  }
  break;
...
*bp++ = cp;                 // запись №2
buflen--;                   // уменьшение №2  <-- нет проверки между ними

Две записи, два уменьшения, без проверки нуля между ними. Когда buflen равно ровно 1, пара уменьшает его до 0, а затем происходит переполнение до SIZE_MAX (18 квинтиллионов). Теперь цикл считает, что буфер бесконечен, и продолжает записывать управляемые атакующим байты вверх по стеку — поверх сохранённых регистров, сохранённого RBP и адреса возврата.

До аутентификации. Функция выполняется до того, как USER/PASS вообще обрабатываются.

Патч

Исправление (коммит 3cc69b8388, «Bug#3521 - Telnet IAC processing stack overflow», выпущено в 1.3.3c) состоит из двенадцати строк. Вся граница безопасности — это:

if (buflen == 0) {
  break;
}

См. patch.diff. Чтение патча показывает, где была рана — это и есть навык.

Лаборатория

Dockerfile компилирует ProFTPD 1.3.3a из исходников исторического снимка Debian, намеренно небезопасно (так выглядел 2010 год):

  • -fno-stack-protector — без канарейки
  • -z execstack — исполняемый стек (без NX)
  • -no-pie — фиксированные адреса бинарника
  • запуск под gdb, который отключает ASLR по умолчанию → детерминированный стек
docker build -t proftpd-133a .
docker rm -f lab133 2>/dev/null
docker run -d --name lab133 --cap-add SYS_PTRACE \
  --security-opt seccomp=unconfined -p 127.0.0.1:2122:21 \
  proftpd-133a sh -c 'gdb -batch -ex "set follow-fork-mode child" \
  -ex "run" -ex "continue" --args /usr/local/sbin/proftpd -n -d1 \
  > /tmp/gdb.txt 2>&1; sleep 600'
python3 exploit.py

Ожидаемый вывод:

[S] 220 ProFTPD 1.3.3a Server (lab-iac) ...
[S] THE SERVER SAID: b'PWNED!!PWNED!!'

(Шеллкод пишет в файловые дескрипторы 0, 1 и 2, потому что мы не хотели зависеть от знания того, какой из них несёт управляющий канал — два из них отвечают.)

Архитектура эксплойта

"SITE " + NOP-слайд + шеллкод + [\xff\xff флуд] + паддинг + [ret] + "\n"
 ^^^^^^^^^^^^^^^^^^^^                             ^^^^
 шеллкод живёт ВНУТРИ буфера               хвост переполнения доставляет
 команды — область, которую никто          только ОДИН адрес
 не трогает
  1. «SITE » поддерживает FTP-парсер в живых — команда обрабатывается чисто.
  2. Шеллкод — это содержимое команды. Буфер — самое безопасное место в стеке: после чтения затрагивается только buf[4102] (завершающий NUL). Всё ниже живых локальных переменных фрейма спокойно.
  3. IAC-флуд доводит buflen до переполнения (см. «Путь» о проблеме чётности).
  4. Слот ret (buf + 4152) получает адрес середины NOP-слайда. Когда pr_cmd_read достигает return 0 после разбора, CPU попадает в слайд и соскальзывает в шеллкод.

Эта инвертированная архитектура — сначала полезная нагрузка, затем флуд, адрес в конце — была проверена против канонического модуля Metasploit (proftp_telnet_iac), который использует ту же компоновку. Их цели имели NX, поэтому им требовалась ROP-цепочка с «четверным разыменованием» указателя res; в нашей лаборатории исполняемый стек, поэтому достаточно одного прямого возврата.

Путь (собственно, смысл этого репозитория)

Финальный эксплойт — 60 строк. Во что это обошлось:

  1. Слепой \xff флуд → ничего. Сервер вежливо закрыл сессию. Корневая причина: buflen начинается с 4102 (ЧЁТНОЕ), и каждая пара IAC уменьшает на 2 — он попадает ровно на 0, никогда на 1. Для переполнения нужна нарушенная чётность. Урок: чтение конечного автомата лучше, чем распыление.

  2. Неверный размер буфера. Первая калиброванная попытка предполагала буфер в 1024 байта. Реальный — MAXPATHLEN+8 = 4104 в Linux/glibc. Флуд остановился на 3 КБ раньше цели. Урок: измеряйте цель, не предполагайте.

  3. Первый SIGSEGV. Циклический узор де Брёйна (Aa0Aa1...) поместил слот возврата на buf+4152, перекрёстно проверенный дважды (математика фрейма + смещение узора). Урок: циклический узор — это измерительная лента, а не эксплойт.

  4. Контроль RIP. Установка слота в 0x4141414141414141 вызвала сбой самой инструкции ret — x86-64 отвергает неканонические адреса, и ошибка происходит на ret, а наше значение ожидает в обратной трассировке. Урок: сбой на ret с вашим значением во фрейме = контроль.

  5. Шеллкод выше слота ret → затёрт. 8 байт перезаписаны указателем кучи (0x4d7838 — позже идентифицирован как выделение пула cmd_rec). Стек-фреймы выше слота принадлежат функциям, которые всё ещё работают между приземлением и перехватом. Урок: переполнение — не последняя запись; программа продолжает жить в стеке, который вы только что испортили.

  6. «Мёртвая зона» ниже слота → тоже исписана. Собственные локальные переменные pr_cmd_read (cmd, buflen, cp) живут прямо там и продолжают сохраняться во время разбора.

  7. Криминалистика аппаратной точкой останова. watch *(long*)ADDR в gdb превратил загадку в камеру: каждая запись в затёртый адрес, с обратной трассировкой, по порядку. Урок: когда вопрос «кто записал эту память?», ответ — в одной команде gdb.

  8. Прочтите эталон, затем поймите его. Канонический модуль подтвердил инвертированную архитектуру. Чтение чужого эксплойта после построения собственной мысленной модели — это изучение; до — это копирование.

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