Bug #6415
closedhttp.header, http.header.raw and http.request_header buffers not populated when malformed header value exists
Description
Hi Suricata Team,
I was reviewing traffic with a malformed Transfer-Encoding header:
HEAD /resources/fonts/SourceSansPro-Regular.ttf HTTP/1.1 Host: localhost Cookie: X-Qlik-Session=13333333-3333-3333-3333-333333333337 X-Qlik-User: UserDirectory=internal;UserId=sa_repository User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Safari/537.36 Content-Length: 430 Transfer-Encoding: , chunked,
See Attached, qlik_bypass.pcap
The goal was to create a rule containing the malformed Transfer-Encoding value and the X-Qlik-* header to reflect Qlik Bypass CVEs (https://www.praetorian.com/blog/qlik-sense-technical-exploit/).
Before testing, I expected that Suricata would populate http.header, http.header.raw and http.request_headers accordingly.
After testing, it appears that Suricata does not populate http.header and http.header.raw. And additionally for Suricata 7+, http.request_headers is limitedly populated. Only Transfer-Encoding header exists as matchable content.
If possible, could Suricata populate http.header, http.header.raw and http.request_headers buffers despite a malformed value being present?
Thanks in advance for reviewing this!
===Testing Notes===
Suricata Sensors Used: 7.0.1, 6, 5, 4.1.0
The following rule was used to confirm Suricata sees the invalid header value:
alert http any any -> any any (msg:"SURICATA HTTP invalid transfer encoding value in request"; flow:established,to_server; app-layer-event:http.invalid_transfer_encoding_value_in_request; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2221005; rev:1;)
Results: For each sensor, 2221005 alerted on qlik_bypass.pcap.
This confirmed that I could use app-layer-event:http.invalid_transfer_encoding_value_in_request; in my final rule. Please see logs/ to review EVE.JSON logs for each engine and an Suricata 7.0.1 output detailing htp_connp_req_data and etc.
The following tests were done to review how Suricata populated http.header, http.header.raw and http.request_headers.
Please see test.rules for the complete set of rules used.
- Test 1, Unbuffered Content only
- sid:11 to sid:16
- For each sensor, all rules alerted.
- Test 2, http.header content only
- sid:21 to sid:26
- For each sensor, no rules alerted.
- Test 3, raw http header only
- sid:31 to sid:36
- For each sensor, no rules alerted.
- Test 5, http.request_header only
- sid:41 to sid:46
- For Suricata 7.0.1, only sid:46 alerts and this rule used http.request_header; content:"Transfer-Encoding". For Suricata 6, 5, and 4.1.0 this test is not applicable because the sticky buffer doesn't exist.
Files
Updated by Victor Julien about 1 year ago
- Status changed from New to Assigned
- Assignee changed from OISF Dev to Philippe Antoine
Philippe can you have a look at what is happening?
Updated by Brandon Murphy about 1 year ago
might be another occurrence of this here
https://forum.suricata.io/t/suricata-rules-http-header-not-working/4120/3
I think, though I don't trust my analysis and defer to Philippe, but it kinda looks like libhtp is considering anything that isn't exactly "chunked" (case insensitive) to be invalid and not parsing the rest of the headers?
https://github.com/OISF/libhtp/blob/0.5.x/htp/htp_transaction.c#L408
https://github.com/OISF/libhtp/blob/0.5.x/htp/bstr.c#L217-L221
https://github.com/OISF/libhtp/blob/0.5.x/htp/bstr.c#L374-L400
Updated by Brandon Murphy 12 months ago
Hello! I am having issues in creating rules for CVE-2023-46747 (Big-IP F5 RCE with mass ITW exploiation)
This appears to be due to the Transfer-Encoding value of chunked, chunked
being considered invalid and the http.request_body buffer not populated.
You can see this being used by Metasploit here
Solid details of the vuln here
https://blog.projectdiscovery.io/cve-2023-46747-5-big-ip-unauthenticated-rce-via-ajp-smuggling/
1. Origin of the Discrepancy: Apache HTTPd receives an HTTP request with a Transfer-Encoding: chunked, chunked header, which it then sends to Tomcat via AJP. Tomcat, expecting Transfer-Encoding to be just chunked, doesn't find a match. It then looks for a Content-length header, which isn't there, so it defaults to assuming a Content-length of 0.
Updated by Philippe Antoine 12 months ago
- Target version changed from TBD to 7.0.3
Updated by Brandon Murphy 12 months ago
https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#transfer-coding
list of "Transfer Codings" registered with IANA
Updated by Philippe Antoine 12 months ago
- Status changed from Assigned to In Review
@Brandon Murphy what do you think about. https://github.com/OISF/libhtp/pull/407 ?
Updated by Philippe Antoine 12 months ago
- Related to Task #6209: libhtp 0.5.46 added
Updated by Brandon Murphy 12 months ago
Philippe Antoine wrote in #note-6:
@Brandon Murphy what do you think about. https://github.com/OISF/libhtp/pull/407 ?
I can't be trusted to understand the possible impacts of this change. Though the removal of the "else" seems to have the possibility of a larger impact.
FWIW, the RFC seems to indicate way more than just "chunked" is valid
https://www.rfc-editor.org/rfc/rfc9112#section-6.1-5
If any transfer coding other than chunked is applied to a response payload body, the sender MUST either apply chunked as the final transfer coding or terminate the message by closing the connection. For example, Transfer-Encoding: gzip, chunked indicates that the payload body has been compressed using the gzip coding and then chunked using the chunked coding while forming the message body.
From the looks of it, and again, i have no idea what i'm really looking at, but it seems like this case of multiple transfer-encoding values might not get addressed.
It seems to me, this assumption mentioned in the code needs to be evaluated given updates to the original HTTP/1.1 RFC. // Make sure it contains "chunked" only.
Updated by Victor Julien 12 months ago
- Subject changed from Suricata not populating http.header, http.header.raw and http.request_header buffers when malformed header value exists to http.header, http.header.raw and http.request_header buffers not populated when malformed header value exists
- Target version changed from 7.0.3 to 8.0.0-beta1
- Label Needs backport to 6.0, Needs backport to 7.0 added
Updated by Philippe Antoine 9 months ago
- Status changed from In Review to Resolved
Updated by Philippe Antoine 9 months ago
- Related to Security #6441: detect: heap use after free with http.request_header keyword added
Updated by Philippe Antoine 9 months ago
https://github.com/OISF/suricata-verify/pull/1641 to merge before closing this
Updated by Philippe Antoine 9 months ago
- Status changed from Resolved to Closed