Project

General

Profile

Actions

Bug #2655

closed

GET/POST HTTP-request with no Content-Length, http_client_body miss

Added by Alexey Vishnyakov about 6 years ago. Updated over 5 years ago.

Status:
Closed
Priority:
Normal
Target version:
Affected Versions:
Effort:
Difficulty:
Label:

Description

Hello, Team!
We've run into troubles with a few threats variants.
Let's imagine some sort of malware which tries to steal a user information.
There are several methods, but one of them is simply send a data via POST request:

POST /... HTTP/1.1
Host: ...
...
Content-Type: application/x-www-form-urlencoded
Content-Length: 22

login=foo&password=*bar*

Below is a simple rule example:

alert http any any -> any any ( \
msg:"TEST 'no Content-Length' vs http_client_body"; \
flow:to_server,established; \
content:"login=foo&password=bar"; http_client_body; \
classtype:trojan-activity; \
sid:1; rev:1;)

Let's imagine that a threat actor will manualy remove the 'Content-Length' option from HTTP header:

POST /... HTTP/1.1
Host: ...
...

login=foo&password=*bar4*

In this case according to HTTP specification a request will be wrong.
But from a network transport side it's not a problem and a packet will be successfully transferred.

The same can be done with GET method although this technique is not recommended.

I've attached two pcap dumps as example.
I've also played a bit with 'Content-Type' and 'Content-Length' options in each session.
As a result, Suricata doesn't detect the body content with 'http_client_body' modifier in cases when 'Content-Length' is absent.
We'll have the same result if just change the 'Content-Length' value to a smaller one: Content-Length: 22 -> Content-Length: 20

A default HTTP server will return an error because it will not resolve a 'login=foo&password=bar' combination as HTTP method of a new request.
But it's up to us how we'll configure our HTTP server.

I believe that removing or reducing the 'Content-Length' field value is a quite easy trick to bypass Suricata detection with http_client_body modifier for a pattern.
I suggest to improve a body length recognizing logic and not to be based on 'Content-Length' value only.

Thank you.
Sincerely yours, Alexey Vishnyakov


Files

post.pcap (52.7 KB) post.pcap Alexey Vishnyakov, 10/31/2018 02:14 PM
get.pcap (53.6 KB) get.pcap Alexey Vishnyakov, 10/31/2018 02:14 PM

Related issues 1 (0 open1 closed)

Copied to Suricata - Bug #3187: GET/POST HTTP-request with no Content-Length, http_client_body miss (4.1.x)ClosedPhilippe AntoineActions
Actions #1

Updated by Victor Julien about 6 years ago

  • Target version deleted (4.1rc2)
Actions #2

Updated by Victor Julien almost 6 years ago

  • Status changed from New to Assigned
  • Assignee set to Philippe Antoine
  • Target version set to 5.0beta1
Actions #3

Updated by Victor Julien almost 6 years ago

  • Description updated (diff)
Actions #4

Updated by Philippe Antoine almost 6 years ago

Thank you Alexey for this report.

From what I understand, the attacker controlled in your case both the client and the server.
And so, he used a slightly different protocol than HTTP.
Yet this slight difference (removing Content-Length header and delimiting content with end of line) is enough to make parsing fail.

As you rightly pointed out, such an attacker could use other schemes, such as using a modified value for Content_Length (-2 when you write it, +2 when you read it)
Another option would be to rename the Content-Length header into Data-Length for instance.
We can imagine many more such schemes.
So, I do not see how Suricata can rightly parse all these slightly different HTTP.

However, things can be done :

- Suricata should report better that there is a parsing error
I proposed these pull requests :
https://github.com/OISF/libhtp/pull/190
https://github.com/OISF/suricata/pull/3704
https://github.com/OISF/suricata-verify/pull/22

- Rules writing should use http_method instead of http_client_body as login=foo&password=bar is indeed parsed as a method by Suricata, and by Apache in your post.pcap
Wireshark parses it as unknown data in a new request (ie different from the POST request)

Actions #5

Updated by Philippe Antoine almost 6 years ago

There are new pull requests :
- https://github.com/OISF/libhtp/pull/191
- https://github.com/OISF/suricata/pull/3705
- https://github.com/OISF/suricata-verify/pull/24

With these, we can have a signature such as

alert http any any -> any any (msg:"test"; flow:established,to_server;
content:"login=foo&password=bar"; http_client_body;
app-layer-event:http.request_body_unexpected;
sid:1; rev:1;)

Actions #6

Updated by Victor Julien over 5 years ago

  • Target version changed from 5.0beta1 to 5.0rc1
Actions #7

Updated by Victor Julien over 5 years ago

  • Copied to Bug #3187: GET/POST HTTP-request with no Content-Length, http_client_body miss (4.1.x) added
Actions

Also available in: Atom PDF