
ProFTPD 1.3.9d — высокий — удалённый — сбой — переполнение BSS в RewriteMap int:utf8trans
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · proftpd-rewrite-utf8trans
Разбор: https://abraxaslabs.tech/research/proftpd-rewrite-utf8trans
Класс: Crash Доступ: Удалённый
ProFTPD 1.3.9d (f59f248) - ProFTPD (proftpd.org)
В contrib-модуле mod_rewrite поставляется RewriteMap int:utf8trans. Этот встроенный механизм копирует аргумент FTP-клиента (до CommandBufferSize, 512 КиБ) в два BSS-буфера по 1024 слота без ограничения размера назначения. Длинное ASCII-имя в STOR приводит к ASan global-buffer-overflow WRITE размером 8. Дочерний процесс сессии аварийно завершается. Демон продолжает работу. Класс Crash. Не RCE.
| ID | CVE пока нет |
| Класс | Crash |
| Доступ | Удалённый (аргумент FTP передаётся в int:utf8trans) |
| CWE | CWE-120 |
| CVSS | High: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, если RewriteRule срабатывает до аутентификации. В лаборатории использовался STOR после входа, поэтому для этого запуска честно PR:L (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H). |
| Продукт | ProFTPD |
| Затронуто | 1.3.9d (f59f248e26bdfa514443e42bf72a145641df635d) contrib mod_rewrite |
| Аутентификация | в лаборатории — аутентифицированный STOR. RewriteRule до аутентификации на USER или аналогичном было бы PR:N. |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
RewriteEngine выключен, пока не настроен. Документированный шаблон — RewriteRule (.*) ${map:$1}. Как только RewriteRule передаёт аргумент клиента через int:utf8trans, ключ длиннее 1024 байт переполняет два статических буфера в дочернем процессе сессии.
| Метод | Точка срабатывания | Привилегия |
|---|---|---|
| FTP-команда, аргумент которой является ключом карты utf8trans, длина > 1024 | rewrite_utf8_to_ucs4, затем utf8_val[i] = ucs4_longs[i] | Доступность (доказано в лаборатории): аварийное завершение дочернего процесса сессии. ASan: global-buffer-overflow WRITE of size 8, затем ABORTING. Prefork: новый вход по-прежнему работал; демон продолжал работу. Короткий STOR из 200 ASCII-байт прошёл успешно. Целостность соседних BSS-областей rewrite выведена косвенно и зависит от раскладки компилятора. |
| RIP / выполнение кода | не заявлено | Закрыто. Полезной нагрузки нет. Класс Crash. Не RCE. |
Подмена RewriteMap через .ftpaccess | CONF_DYNDIR | Закрыто. RewriteMap не разрешён в .ftpaccess. |
prg: shell | такого типа карты нет | Закрыто. FIFO — это построчный ввод-вывод. |
Доказано в лаборатории vs выведено косвенно: ASan WRITE размером 8, аварийное завершение дочернего процесса сессии, успешный контрольный запуск с коротким аргументом и вход после срабатывания — доказаны в лаборатории. RIP/RCE не заявлены.
Issue 2173 исправил однобайтовый OOB в int:unescape на этой версии. Этот остаток — int:utf8trans. Другой встроенный механизм. Другая ошибка.
Я зафиксировал тег v1.3.9d в proftpd/proftpd. Урожай CVE 2026 года и публичные GitHub issues, всё ещё присутствующие в этом архиве (2170, 2173, 2175, 2180, 2095, 2256, 2286, 2319, 2330, 2301), были в списке пропуска. Стандартный core FTP с примером basic.conf не дал мне неопубликованного Crit/High. Contrib rewrite дал.
rewrite_map_int_utf8trans (contrib/mod_rewrite.c) содержит:
static unsigned char utf8_val[PR_TUNABLE_BUFFER_SIZE]; /* 1024 */
static unsigned long ucs4_longs[PR_TUNABLE_BUFFER_SIZE]; /* 1024 */
ucs4strlen = rewrite_utf8_to_ucs4(ucs4_longs, strlen(key), (unsigned char *) key);
rewrite_utf8_to_ucs4 записывает по одному unsigned long на каждый ASCII-байт без ограничения. PR_TUNABLE_CMD_BUFFER_SIZE равен 512 KiB. В issue 2173 уже исправлен unescape. Этот map не входил в то исправление.
Неверные пути: считать 2173 этим багом; заявлять о RIP, потому что ASan сообщил WRITE of size 8; надеяться, что .ftpaccess сможет подсадить RewriteMap. Первое — это другая функция. Второе — всё ещё Crash. Третье — CONF_DYNDIR.
ASan вместе со стоковым libcrypt даёт SIGSEGV на PASS ещё до rewrite-синка. Лаборатория предзагружает крошечную заглушку crypt(3), чтобы логин работал. Эта заглушка не является эксплойтом.
python3 proftpd-rewrite-utf8trans-Abraxas-Labs.py
или:
cd lab
./run.sh
Loopback 127.0.0.1:18740 плюс пассивные 18741-18750. Проект Compose proftpd-rewrite-utf8trans. Свидетель PROFTPD-REWRITE-UTF8TRANS-WITNESS. Образ — сборка 1.3.9d mod_rewrite с ASan. Контрольный STOR 200 ASCII-байт завершается успешно. STOR 2048 ASCII-байт вызывает ASan global-buffer-overflow WRITE размером 8, и дочерний процесс сессии аварийно завершается. Новый вход после срабатывания по-прежнему работает.
SUCCESS PROFTPD-REWRITE-UTF8TRANS asan=global-buffer-overflow write=yes child-dead=yes PROFTPD-REWRITE-UTF8TRANS-WITNESS
Ограничить длину назначения rewrite_utf8_to_ucs4 значением PR_TUNABLE_BUFFER_SIZE-1. Прекратить запись за пределы ucs4_longs / utf8_val. Отклонять или усекать ключ карты, который не помещается.
f59f248e26bdfa514443e42bf72a145641df635d)contrib/mod_rewrite.c rewrite_utf8_to_ucs4 / rewrite_map_int_utf8transint:unescapeGNU Affero GPL v3.0. См. LICENSE. Только для лабораторной среды с loopback. Без гарантий.