Project

General

Profile

Actions

Bug #2706

closed

Malformed SEQ value in TCP connection - detection bypass

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

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
Affected Versions:
Effort:
Difficulty:
Label:

Description

Hello, team!

There is a serious problem in all last (maybe all) Suricata versions. Let me show you a method how to bypass the Suricata detection

I want to detect a HTTP request with first 'xss' param in URI. Look at these 2 rules (you can also find them in attached file rules.txt):

alert http any any -> any any ( \
msg:"Test 1"; \
content:"?xss="; \
classtype:web-application-attack; \
sid:1; rev:1;)

alert http any any -> any any ( \
msg:"Test 2"; \
content:"?xss="; http_uri; \
classtype:web-application-attack; \
sid:2; rev:1;)

The only one difference between them is a 'http_uri' option (it doesn't exist in first and exists in second)
Obviously, the second rule is better because an exact buffer for match is specified

I've prepared the default LAMP server on my test machine with Ubuntu OS (192.168.56.3 - IP address)
Now I want to perform a very simple sequence of HTTP requests (you can find a Python script example in attachment: py_request.py):
- GET h[t]tp://192.168.56.3/index.html
- GET h[t]tp://192.168.56.3/index.html?xss=<img src=x onerror=alert(0)>
The first request is legitimate. The second is malicious
It's important to make both requests in one TCP session

You can find a captured PCAP dump in attachment: py_request_correct.pcap
Both rules will successfully detect a malicious activity

And what now?
1). Find a packet with a second GET request (num. 19): 19 0.009672 192.168.56.1 192.168.56.3 HTTP 248 GET /index.html?xss=%3Cimg%20src=x%20onerror=alert(0)%3E HTTP/1.1
2). Find a sequence number value: 0x2951efaf (big endian)
3). Manualy change it just in PCAP: increment of 1 for example - 0x2951efb0 (big endian)

You can find a modified PCAP in attachment: py_request_malformed.pcap
And now only first rule will successfully detect a malicious activity!

To eliminate any doubts I've made a Python script which helps me to reproduce this situation without PCAP patching
You can find the script in attachment: poc.py

A destination was a default LAMP again on my another test machine with Kali OS (192.168.56.6 - IP address)
I've reduced a default HTML page to "Kali pong" content only because it's too boring to process several server replies with Scapy
You can again find PCAPs in attachment:
- scapy_correct.pcap - a traffic generated with correct TCP values
- scapy_malformed.pcap - a traffic generated with malformed SEQ value

Detection problem appears again

It's interesting that
- the first rule continues to detect despite the 'http' protocol fact. Another words - http session is not broken
- 'flow:established' - this option doesn't necessary in case of 'http' protocol, but if you'll add it in the rule - detection will not disappear
- 'http_*' - you can test with other options in other parts of HTTP request in the second rule: http_user_agent, http_header, http_method - the problem remains
It looks like the Suricata stops to parse protocol structures after malformed SEQ value. But the wrong value is not a problem for connection: it looks like we missed some data during transmission - it's not a server problem, and a client just ignores it.

As a result: I can easily bypass a detection by perfoming a few clean requests, changing a SEQ value and continue to send requests in the same TCP session, which are malicious now
Usually a real ruleset contains not less than 2/3 of http-based rules. And due to a fact that almost all of them contain some http modifier or sticky buffer we believe it's important issue.

Could you confirm that?
Shoud I request CVE by myself or you'll assist with that?

Thank you in advance!

Sincerely yours, Alexey Vishnyakov
Lead network analyst
company “Security Code”


Files

poc.py (1.67 KB) poc.py Alexey Vishnyakov, 11/23/2018 10:24 AM
py_request.py (156 Bytes) py_request.py Alexey Vishnyakov, 11/23/2018 10:24 AM
py_request_correct.pcap (25.5 KB) py_request_correct.pcap Alexey Vishnyakov, 11/23/2018 10:24 AM
py_request_malformed.pcap (25.5 KB) py_request_malformed.pcap Alexey Vishnyakov, 11/23/2018 10:24 AM
rules.txt (260 Bytes) rules.txt Alexey Vishnyakov, 11/23/2018 10:24 AM
scapy_correct.pcap (3.88 KB) scapy_correct.pcap Alexey Vishnyakov, 11/23/2018 10:24 AM
scapy_malformed.pcap (4.3 KB) scapy_malformed.pcap Alexey Vishnyakov, 11/23/2018 10:24 AM
Actions #1

Updated by Victor Julien about 6 years ago

  • Private changed from No to Yes
Actions #2

Updated by Victor Julien about 6 years ago

I have trouble seeing what the issue is. When using the bad SEQ the receiving server sees an out of order packet and doesn't process it until the missing packets arrive, which never happens. I tested the poc against 2 servers, and both don't log the 2nd request, nor do they respond to it.

AFAICS, what the POC does, is sort of simulate packet loss.

Suricata doesn't process the 2nd request as HTTP because it has no way yet to recover from a data gap for HTTP.

The forged PCAPs seem to be just that, traffic with the TCP sequences messed up. You can see that [1 bytes missing in capture file] message in Wireshark. This means that in real traffic the server process would not get this request and thus wouldn't respond.

Maybe I'm missing something obvious, but currently I don't see how this would be a security issue.

Actions #3

Updated by Victor Julien about 6 years ago

  • Status changed from New to Rejected
  • Priority changed from High to Normal

Original reporter agreed with the analysis, so closing and setting back to public.

Actions #4

Updated by Victor Julien about 6 years ago

  • Private changed from Yes to No
Actions

Also available in: Atom PDF