Bug #9096
openhttp1: 100-continue based inspection bypass of http.stat_code
Description
When a client uses Expect: 100-continue and the server answers a bare 100 Continue, the HTTP parser rewinds the same response tx at the empty line ending the 100's headers: headers cleared, progress back from HEADERS to LINE - but neither the tx's stat-code byte buffer (still 100) nor the detection engine's per-tx bookkeeping is reset. On ordinary, spec-compliant traffic this yields a false positive and a false negative:
- False positive (double alert). The 100 line commits at
HEADERS; its final run matches the100buffer once and stores per-txdetect_progress(LINE + 1). The rewind leaves the stale100buffer with the tx atLINE; when the final 200's line arrives the engine re-runs non-terminally and matches it again - the 100 line alerts twice. - False negative (the bypass). The final
200is parsed on the same tx and refreshes both the buffer and the numeric status - the http log correctly records200. But the staledetect_progresssurvives: when the tx reachesCOMPLETEthe prefilter seesdetect_progress > tx_min_progressand skips the stat-code engine for the tx entirely - the final response's stat code is never inspected, so anyhttp.stat_coderule on it is dead for such flows.
The numeric status is not the detection input, but it triggers the rewind itself (the parser keys on 100 at the empty line) - that is what keeps the final 200 on the poisoned tx. Scope: only the stat-code buffer - the final response's headers/body and request-side keywords still detect normally. IPS mode hits this for any 100-continue exchange; NIDS mode when the 100 line commits in its own parse cycle (client auto-ACKs the 100 response). SV MR 9 reproduces both end-to-end.
I wonder if we should create a new tx instead of doing the rewind. Suricata generally expects the tx state to be monotonic.