
Apache Traffic Server 10.2.0 - Élevé - À distance - Résidu de privilèges - casse de méthode ip_allow
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · ats-ipallow-method-case
Classe : Privilège résiduel Portée : Distante
Apache Traffic Server 10.2.0 (b1df7334) - Apache Software Foundation
Les méthodes HTTP/1 à casse mixte contournent le refus par défaut de ip_allow.yaml pour PURGE/PUSH/DELETE/TRACE et le TUNNEL vers l'origine remappée avec l'uid d'ATS. L'analyse YAML et celle de @method dans le remap sont insensibles à la casse. La tokenisation H1 effectue ensuite un strncmp sur les octets de la requête et renvoie -1 en cas de non-concordance de casse. L'inversion du refus traite ce jeton inconnu comme autorisé. Le :method HTTP/2 est insensible à la casse et reste refusé. Les PURGE/PUSH du cache nécessitent toujours un wksidx bien connu, donc la casse mixte ne purge ni ne pousse le cache.
Il s'agit d'un résidu de l'ACL de méthode entrante par défaut, et non de CVE-2026-33267 (hop-by-hop), ni de l'ACL de remap inversée vide non standard (corrigée sur ce pin).
| ID | pas encore de CVE |
| Classe | Privilège résiduel |
| Portée | Distante (HTTP/1 non authentifié depuis un client non-loopback) |
| CWE | CWE-178, CWE-863 |
| CVSS | Élevé : 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N |
| Produit | Apache Traffic Server |
| Affecté | 10.2.0 (b1df7334b39a878971c376da849e8da4984918b6) proxy inverse par défaut |
| Auth | aucune. ip_allow.yaml par défaut. remap_required: 1 plus un map. |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18710 uniquement. Image ats-10.2.0-lab:local. |
J'ai épinglé le tag 10.2.0, commit b1df7334b39a878971c376da849e8da4984918b6. Dernière version stable du 17 août 2026. Image construite depuis les sources, pas un gadget.
Atteindre un proxy inverse typique (remap_required: 1 plus un map) en HTTP/1 depuis une adresse non-loopback. 127.0.0.1 est autorisé en ALL. plugin.config vide. ip_allow.yaml par défaut.
| Méthode | Destination | Privilège |
|---|---|---|
HTTP/1 delete / DeLeTe après remap depuis un sidecar 172.x | hdrtoken_method_tokenize puis process_quick_http_filter puis TUNNEL METHOD_NOT_SUPPORTED (HdrToken.cc:512-528, HttpTransact.cc:6855-6858) | Intégrité (prouvé en lab) : origine 200 DELETED ATS-IPALLOW-METHOD-CASE-WITNESS. DELETE en majuscules donne 403. Méthode d'origine avec l'uid d'ATS. |
HTTP/1 trace | même TUNNEL | Reconnaissance (prouvé en lab) : origine 200 TRACE-OK. ATS ne construit pas l'écho TRACE (wksidx n'est pas TRACE). TRACE en majuscules donne 403. |
HTTP/1 purge / push | TUNNEL de méthode inconnue, pas une opération de cache | Intégrité (cache ATS) : fermé (prouvé en lab). L'origine a vu PURGE-ORIGIN / PUSH-ORIGIN. Les opérations de cache nécessitent un wksidx bien connu. push_method_enabled vaut 0 par défaut. |
| Même requête à casse mixte | un saut d'origine supplémentaire | Disponibilité (prouvé en lab) : pas de mort du processus. |
Prouvé en lab vs déduit : refus en majuscules, tunnel DELETE/TRACE à casse mixte, PURGE/PUSH du cache fermés : lab. DELETE/TRACE vers l'origine uniquement si cette origine normalise la casse de la méthode (IIS / certains Java). Les origines sensibles à la casse selon la RFC 9110 (nginx, httpd, Go) répondent 501. L'origine du lab normalise la casse.
Nécessite : HTTP/1 depuis un client non-loopback. remap_required: 1 plus un map. Refus entrant par défaut de PURGE/PUSH/DELETE/TRACE. Le :method HTTP/2 en nocase reste refusé.
| Surface | Lab |
|---|---|
DELETE / TRACE en casse exacte depuis 172.x | 403, origine non atteinte |
:method HTTP/2 en casse mixte | tokenisation nocase, toujours refusé |
purge / push en casse mixte comme opérations de cache ATS | l'origine a vu le verbe ; le chemin de cache est resté fermé |
Refus de destination CONNECT (0.0.0.0/8, RFC1918, link-local, ::ffff:0:0/96) | ip_allow.yaml sortant par défaut |
Échec de remap_required: 1 | 404, pas un relais ouvert |
| ACL de remap vide-nonstandard inversée | correctif CHANGELOG maintenu |
CVE-2026-33267 hop-by-hop / suppression de @ | fermé sur ce pin |
Le ip_allow.yaml par défaut est l'ACL de méthodes distantes standard. Le chargement YAML utilise hdrtoken_tokenize (nocase). L'inversion DENY définit ensuite _method_mask = ALL & ~listed et _deny_nonstandard_methods = true avec une liste nonstandard vide (IPAllow.cc:545-548).
L'analyse HTTP/1 tokenise avec hdrtoken_method_tokenize. Le DFA est insensible à la casse ; l'helper effectue ensuite un strncmp des octets de la requête contre la chaîne bien connue et renvoie -1 en cas de non-concordance de casse :
retval = hdrtoken_tokenize(string, string_len, &string_out);
if (retval >= 0) {
if (strncmp(string, string_out, string_len) != 0) {
// Not a case match
retval = -1;
}
}
EndRemapRequest demande isNonstandardMethodAllowed pour method == -1 (IPAllow.h:365-376). Un ensemble nonstandard vide plus deny-nonstandard donne !method_in_set, donc la casse mixte est autorisée. is_this_http_method_supported(-1) est faux. METHOD_NOT_SUPPORTED définit ProxyMode_t::TUNNELLING et renvoie vrai. La documentation indique qu'ATS transmet les méthodes inconnues à l'origine. La recherche dans le cache est ignorée en mode TUNNELLING.
La pseudo-en-tête :method de HTTP/2 passe par HTTPHdr::method_set -> hdrtoken_tokenize sans vérification de casse. Le delete en H2 devient DELETE et est refusé. Ce reliquat concerne HTTP/1.
Fausses pistes : considérer que les origines sensibles à la casse de la RFC 9110 rendent la liste de refus inopérante (PURGE/PUSH du cache ATS restent fermés ; DELETE/TRACE vers l'origine est le reliquat) ; faire un curl depuis 127.0.0.1 (allow ALL) ; prétendre à une purge de cache ; reclasser en hop-by-hop.
Mise en scène : un reverse shell. L'oracle est une chaîne témoin sur l'origine après un 403 en majuscules.
python3 ats-ipallow-method-case-Abraxas-Labs.py
ou
cd lab
./run.sh