Bug #2706
closedMalformed SEQ value in TCP connection - detection bypass
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