[Snort-devel] Double Content-Length headers causes matching string inside http_client_body to fail (http_inspect preprocessor)

Pablo Artuso artusopablo at ...2499...
Thu Jun 19 09:50:18 EDT 2014


Hello,

I'm experiencing an issue when http_inspect preprocessor handles an HTTP
packet with two identical Content-Length headers present.
When two identical headers (with the same value) are present, the rule
trying to match a string inside http_client_body fails. The only header
that triggers this condition is Content-Length.

This could be a mechanism to evade HTTP signatures based on http_inspect
preprocessor.

OS: Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux
Snort Package: snort (2.9.2.2-3)
Preprocessors enabled: stream5, http_inspect
(Find below a snort.conf can be used for testing purposes)

Steps to reproduce the bug (python+scapy):

1. Install Scapy (http://www.secdev.org/projects/scapy/)
2. Install Snort version 2.9.2 (I'm using the apt-get from Debian
repositories)
3. Install the supplied snort.conf enabling http_inspect and stream5
preprocessors
4. Start Scapy and try the examples below.

Best regards,

Pablo


--- Example 1: HTTP POST packet with double Content-Length ---

DST_SERVER = 'xxx.xxx.xxx.xxx' # Complete!

httpheaderN =  'POST / HTTP/1.1\r\nHost: '+ DST_SERVER +'\r\nUser-Agent:
Wget/1.13.4 (linux-gnu)\r\nContent-Length: 86\r\nContent-Type: text/plain;
charset=utf-8\r\nContent-Length: 86\r\n\r\n'

httpbodyN = "Nobody can go back and start a new beginning, but anyone can
start today a new ending."


pDouble = IP(dst=DST_SERVER) / TCP(dport=80)  / (httpheaderN+httpbodyN)

send(pDouble) # should trigger both rules! Fails to match http_client_body
rule

--- End Example 1 ---

--- Example 2 ---
DST_SERVER = 'xxx.xxx.xxx.xxx' # Complete!

httpheaderD =  'POST / HTTP/1.1\r\nHost: '+ DST_SERVER +'\r\nUser-Agent:
Wget/1.13.4 (linux-gnu)\r\nContent-Type: text/plain;
charset=utf-8\r\nContent-Length: 86\r\n\r\n'

httpbodyD = "Nobody can go back and start a new beginning, but anyone can
start today a new ending."

pNormal = IP(dst= DST_SERVER) / TCP(dport=80)  / (httpheaderD+httpbodyD)

send(pNormal) # Should trigger both rules! OK

--- End Example 2 ---


--- used snort.conf ---
output unified2: filename snort_unified2.out, limit 128
output alert_fast

preprocessor stream5_global: \
  track_tcp yes \
  track_udp yes
preprocessor stream5_tcp: \
  policy bsd, \
  timeout 86400, \
  ports all
preprocessor stream5_udp: \
  timeout 86400

preprocessor http_inspect: \
  global \
  iis_unicode_map unicode.map 1252

preprocessor http_inspect_server: \
  server default \
  profile all \
  client_flow_depth 0 \
  server_flow_depth 0 \
  post_depth 0 \
  extended_response_inspection \
  ports { 80 } http_methods { GET POST PUT SEARCH MKCOL COPY MOVE LOCK
UNLOCK NOTIFY POLL BCOPY BDELETE BMOVE LINK UNLINK OPTIONS HEAD DELETE
TRACE TRACK CONNECT SOURCE SUBSCRIBE UNSUBSCRIBE PROPFIND PROPPATCH
BPROPFIND BPROPPATCH RPC_CONNECT PROXY_SUCCESS BITS_POST CCM_POST SMS_POST
RPC_IN_DATA RPC_OUT_DATA RPC_ECHO_DATA }


var DST_SERVER xxx.xxx.xxx.xxx # Complete!! and erase this comment!

alert tcp any any -> $DST_SERVER 80 (  flow: to_server; content: "Nobody";
nocase; \
http_client_body;  content: "Beginning"; nocase; http_client_body;  msg:
"Rule with http_client_body ";  \
sid: 2;)

alert tcp any any -> $DST_SERVER 80 (  flow: to_server; content: "Nobody";
nocase; \
content: "Beginning"; nocase; msg: "Rule without http_client_body ";  sid:
1)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.snort.org/pipermail/snort-devel/attachments/20140619/c5655828/attachment.html>


More information about the Snort-devel mailing list