
ProFTPD 1.3.9d – Hoch – Remote – Absturz – RewriteMap int:utf8trans BSS-Überlauf
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · proftpd-rewrite-utf8trans
Write-up: https://abraxaslabs.tech/research/proftpd-rewrite-utf8trans
Klasse: Crash Reichweite: Remote
ProFTPD 1.3.9d (f59f248) - ProFTPD (proftpd.org)
Das contrib-Modul mod_rewrite liefert RewriteMap int:utf8trans mit. Dieses Builtin kopiert ein FTP-Argument des Clients (bis zu CommandBufferSize, 512 KiB) in zwei BSS-Puffer mit jeweils 1024 Slots, ohne die Zielgröße zu begrenzen. Ein langer ASCII-STOR-Name führt zu einem ASan-global-buffer-overflow-WRITE der Größe 8. Der Session-Child-Prozess bricht ab. Der Daemon läuft weiter. Klasse Crash. Kein RCE.
| ID | noch keine CVE |
| Klasse | Crash |
| Reichweite | Remote (FTP-Argument, das an int:utf8trans übergeben wird) |
| 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, falls die RewriteRule pre-auth ist. Das Lab verwendete STOR nach dem Login, daher ist PR:L für diesen Lauf ehrlich (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H). |
| Produkt | ProFTPD |
| Betroffen | 1.3.9d (f59f248e26bdfa514443e42bf72a145641df635d) contrib mod_rewrite |
| Auth | Das Lab verwendet authentifiziertes STOR. Eine pre-auth RewriteRule auf USER oder ähnliches wäre PR:N. |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
RewriteEngine ist deaktiviert, bis es konfiguriert wird. Das dokumentierte Muster ist RewriteRule (.*) ${map:$1}. Sobald eine RewriteRule das Client-Argument durch int:utf8trans leitet, überläuft ein Schlüssel, der länger als 1024 Bytes ist, zwei statische Puffer im Session-Child-Prozess.
| Methode | Sink | Privileg |
|---|---|---|
| FTP-Befehl, dessen Argument der utf8trans-Map-Schlüssel ist, Länge > 1024 | rewrite_utf8_to_ucs4, dann utf8_val[i] = ucs4_longs[i] | Verfügbarkeit (im Lab nachgewiesen): Absturz des Session-Child-Prozesses. ASan: global-buffer-overflow WRITE of size 8, dann ABORTING. Prefork: Ein frischer Login funktionierte weiterhin; der Daemon blieb oben. Ein kurzes STOR von 200 ASCII-Bytes überstand dies. Die Integrität benachbarter Rewrite-BSS wird vermutet und hängt vom Compiler-Layout ab. |
| RIP / Codeausführung | nichts beansprucht | Ausgeschlossen. Kein Payload. Klasse Crash. Kein RCE. |
.ftpaccess-Plant von RewriteMap | CONF_DYNDIR | Ausgeschlossen. RewriteMap ist in .ftpaccess nicht erlaubt. |
prg:-Shell | kein solcher Map-Typ | Ausgeschlossen. FIFO ist Zeilen-I/O. |
Im Lab nachgewiesen vs. vermutet: ASan-WRITE der Größe 8, Abbruch des Session-Child-Prozesses, überlebende Kontrolle mit kurzem Argument und Login nach dem Auslösen sind im Lab nachgewiesen. RIP/RCE wird nicht beansprucht.
Issue 2173 hat auf diesem Pin den ein-Byte-OOB von int:unescape gepatcht. Dieser Rest ist int:utf8trans. Anderes Builtin. Anderer Bug.
Ich habe proftpd/proftpd auf Tag v1.3.9d gepinnt. Die CVE-Ernte 2026 und die öffentlichen GitHub-Issues, die noch in diesem Tarball steckten (2170, 2173, 2175, 2180, 2095, 2256, 2286, 2319, 2330, 2301), bildeten die Skip-Liste. Der Standard-Core-FTP mit Beispiel-basic.conf lieferte mir kein unveröffentlichtes Crit/High. Contrib rewrite schon.
rewrite_map_int_utf8trans (contrib/mod_rewrite.c) hat:
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 schreibt ein unsigned long pro ASCII-Byte mit keiner Obergrenze. PR_TUNABLE_CMD_BUFFER_SIZE beträgt 512 KiB. Issue 2173 hat bereits unescape behoben. Diese Map war nicht Teil dieses Fixes.
Irrwege: 2173 für diesen Bug zu halten; RIP zu behaupten, weil ASan WRITE der Größe 8 meldete; zu hoffen, dass .ftpaccess eine RewriteMap platzieren könnte. Das erste ist eine andere Funktion. Das zweite ist weiterhin Crash. Das dritte ist CONF_DYNDIR.
ASan plus Standard-libcrypt führt bei PASS zu SIGSEGV, bevor die Rewrite-Senke erreicht wird. Das Lab lädt einen winzigen crypt(3)-Stub vor, damit der Login funktioniert. Dieser Stub ist kein Exploit.
python3 proftpd-rewrite-utf8trans-Abraxas-Labs.py
oder:
cd lab
./run.sh
Loopback 127.0.0.1:18740 plus passiv 18741-18750. Compose-Projekt proftpd-rewrite-utf8trans. Witness PROFTPD-REWRITE-UTF8TRANS-WITNESS. Das Image ist ein ASan-Build von 1.3.9d mod_rewrite. Kontroll-STOR von 200 ASCII-Bytes ist erfolgreich. STOR von 2048 ASCII-Bytes ist ein ASan global-buffer-overflow WRITE der Größe 8 und der Session-Kindprozess bricht ab. Ein frischer Login nach dem Trigger funktioniert weiterhin.
SUCCESS PROFTPD-REWRITE-UTF8TRANS asan=global-buffer-overflow write=yes child-dead=yes PROFTPD-REWRITE-UTF8TRANS-WITNESS
Begrenze die Ziel-Länge von rewrite_utf8_to_ucs4 auf PR_TUNABLE_BUFFER_SIZE-1. Beende das Schreiben über ucs4_longs / utf8_val hinaus. Lehne einen Map-Schlüssel, der nicht passt, ab oder kürze ihn.
f59f248e26bdfa514443e42bf72a145641df635d)contrib/mod_rewrite.c rewrite_utf8_to_ucs4 / rewrite_map_int_utf8transint:unescapeGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.