You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Content-Length with whitespace before a list comma (5 ,5) is accepted, then framed as no body #60
UltraHardenedParser accepts a Content-Length list with whitespace before a comma. BodyFramingDetector then frames that request as having no body:
Content-Length:
accepted
DetectBodyFraming
5
yes
ContentLength 5
5,5
yes
ContentLength 5
5, 5
yes
ContentLength 5
5 ,5
yes
None
5\t, 5
yes
None
5 , 5
yes
None
The two halves disagree about the whitespace:
The validator allows OWS on both sides of each element. SemIsValidContentLengthValue (UltraHardenedParser.FullHeader.ROM.cs:371) skips OWS after each number, before the comma (:418).
SemHasConflictingCommaSeparatedCL trims that OWS before comparing the elements.
The framing parse keeps it:
// BodyFramingDetector.cs, ParseContentLengthDigitsintcomma=value.IndexOf((byte)',');if(comma>=0)value=value[..comma];// :150 - "5 ": the space before the comma stays...if(b<(byte)'0'||b>(byte)'9')return-1;// :158
-1 is not > 0 (:52), so DetectBodyFraming returns NoBody (:56).
Why it matters
The body bytes are read as the start of the next request on the connection. A front end that frames this header as 5 bytes, as RFC 9110 §8.6 intends, and a back end on Glyph11 then disagree about where the request ends. That is request smuggling, from a header the hardened parser has validated.
Responses go through the same parse: DetectResponseBodyFraming returns UntilClose for Content-Length: 5 ,5 (:131). A client then reads every later byte on the connection as this response's body.
Fix
Trim OWS from the first element before parsing it. Better, parse it with the validator's own loop, so the two can no longer disagree. Ktron's Kotlin port of Glyph11 fixes this in MDA2AV/Ktron@c6504d6.
main (f5d2cc1) and the NuGet package 0.3.7 both give the table above. These vectors are in the request corpus of Ktron's port, which found them.
Activity