Snort Rule - HTTP Body Content - snort

I am trying to create a simple rule to alert when "MZ" are the first two characters in the HTTP body.
My current rule is:
alert tcp any any -> any any (msg:"Test"; content:"MZ"; depth: 2; http_client_body; sid:51; rev:1;)
But this finds no results despite "MZ" definitely being present in the HTTP body.
Assistance much appreciated.

After seeking assistance from a few other sources, it turns out I was asking snort to look in the wrong place:
The correct rule is below:
alert tcp any any -> any any (msg:"Test"; file_data; content:"MZ"; depth: 2; sid:51; rev:1;)
Instead of http_client_body after the content string, the rule needed file_data before the content string.
http_client_body = the request body
file_data = the response body*
(*It's more complicated than that, but this is sufficient to explain this case. Please see the Snort documentation for further reference)

Related

Filter by Request Header in Charles Proxy?

Is it possible to filter by HTTP request headers in Charles Proxy? I'm able to configure visual highlighting in the sequence list for requests matching the header pattern, but I'd prefer to reduce the list of requests to only those matching the request header pattern.
Unfortunately, It's a limitation from Charles that we couldn't filter by Request/Response Header.
If you don't mind, please check out Proxyman which has many built-in filters that fit your need.
Filter: URL, Query String, Request Header, Response Header, Body, Method, Status Code, Comment, Color
Matching Rule: Contains, Not Contains, Start With, End With, Equal, Not Equal, Regex
Document: https://docs.proxyman.io/basic-features/content-filter
Disclaimer: I'm a creator of Proxyman and I hope it answers your question.

Snort Rule : detect request abc.jsp and cookie value = null

I would like to detect and send alert with snort for:
request /abc/abc.jsp and
cookie abc value is null
I tried:
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORT (sid:xxx; gid:1; content:"/abc/abc.php"; http_uri; pcre:"abc=''"; msg:"BLACKLIST - request without cookie ";)
but it does not seem to work...
Your pcre content is not following the correct syntax. You need to put the content between forward slashes (/). See the manual here. So your pcre option should look like the following:
pcre:"/abc=''/"
I would also note that this pcre probably isn't sufficient for what you want to do. I would do something like the following:
pcre:"/abc=('|\")(\1)/C"
This will allow you to look for both single and double quotes so this would match either of the following:
abc=''
abc=""
Also adding the C at the end of the pcre will tell snort to only check the following:
Match normalized HTTP request or HTTP response cookie
Which is more efficient and less prone to false positive since it's only checking the normalized cookie content.
It's also less prone to false negatives because it's checking the normalized content of the cookie because if the cookie is for some reason URL encoded ' would be %27 and " would be %22 and the pcre won't match. Giving the C option snort will check the normalized payload and would match.
So your final rule might look like:
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORT (sid:xxx; gid:1; content:"/abc/abc.php"; http_uri; pcre:"/abc=('|\")(\1)/C"; msg:"BLACKLIST - request without cookie ";)
Cookie structure: name=value;
If u want to detect cookie abc value is null, use pattern abc=;
alert tcp any any -> any any (msg:"test-cookie"; content:"abc=\;"; http_cookie; nocase;)

How to pack a variable into an HTTP GET request in socket.send() - Python 2.7

First off thanks for reading!
Second off YES I have tried to find the answer! :) Perhaps I haven't found it because I'm not using the right words to describe my problem, but it's been about 4 hours that I've been trying to figure it out now and I'm getting a little loopy trying to piece it together on my own.
I am very new to programming. Python is my first language. I am on my third Python course. I have an assignment to use the socket library (not urllib library - I know how to do that) to make a socket and use GET to receive information. The problem is that the program needs to take raw input for the URL in question.
I have everything else the way I want it, but I need to know the syntax that I'm supposed to be using INSIDE my "GET" request in order for the HTTP message to include the requested document path.
I have tried (obviously not all together lol):
mysock.send('GET (url) HTTP/1.0\n\n')
mysock.send( ('GET (url) HTTP:/1.0\n\n'))
mysock.send(('GET (url) HTTP:/1.0\n\n'))
mysock.send("GET (url) HTTP/1.0\n\n")
mysock.send( ("'GET' (url) HTTP:/1.0\n\n"))
mysock.send(("'GET' (url) 'HTTP:/1.0\n\n'"))
and:
basically every other configuration of the above (, ((, ( (, ', '' combinations listed above.
I have also tried:
-Creating a string using the 'url' variable first, and then including it inside mysock.send(string)
-Again with the "string-first" theory, but this time I used %r to refer to my user input (so 'GET %r HTTP/1.0\n\n' % url basically)
I've read questions here, other programming websites, the whole chapter in the book and the whole lectures/notes online, I've read articles on the socket library and the .send(), and of course articles on GET requests... but I'm clearly missing something. It seems most don't use socket library when they can use urllib and I don't blame them!!
Thank you again...
Someone from the university posted back to me that the url variable can concatenated with the GET syntax and assigned to a string variable which can then be called with .send(concatenatedvariable) - I had mentioned trying that but had missed that GET requires a space after the word 'GET' so of course concatenating didn't include a space and that blew it. In case anyone else wants to know :)
FYI: A fully quallified URL is only allowed in HTTP/1.1 requests. It is not the norm, though, as HTTP/1.1 requires setting the Host header. The relevant piece of reading would've been RFC 7230, sec. 3.1.1 and possibly RFC 3986. The syntax of the parameters is largely borrowed from the CGI format. It is in no way enforced, however. In a nutshell, everything put together would look like this on the wire:
GET /path?param1=value1&param2=value2 HTTP/1.1
Host: example.com
As a final note: The line delimiter in HTTP is CRLF (\r\n). For robustness, a simple linefeed is acceptable as well but not recommended.

Ensure Completeness of HTTP Messages

I am currently working on an application that is supposed to get a web page and extract information from its content.
As I learned from my research (or as it seems to me at least), there is no ideal way to determine the end of an HTTP message.
Generally, I found two different ways to do so:
Set O_NONBLOCK flag for the socket and fetch data with recv() in a while loop. Assume that the message is complete and break if it occurs once that there are no bytes in the stream.
Rely on the HTTP Content-Length header and determine the end of the message with it.
Both ways don't seem to be completely safe to me. Solution (1) could possibly break the recv loop before the message was completed. On the other hand, solution (2) requires the Content-Length header to be set correctly.
What's the best way to proceed in this case? Can I always rely on the Content-Length header to be set?
Let me start here:
Can I always rely on the Content-Length header to be set?
No, you can't. Content-Length is an optional header. However, HTTP messages absolutely must feature a way to determine their body length if they are to be RFC-compliant (cf RFC7230, sec. 3.3.3). That being said, get ready to parse on chunked encoding whenever a content length isn't specified.
As for your original problem: Ensuring the completeness of a message is actually something that should be TCP's job. But as there are such complicated things like message pipelining around, it is best to check for two things in practice:
Have all reads from the network buffer been successful?
Is the number of the received bytes identical to the predicted message length?
Oh, and as #MartinJames noted, non-blocking probably isn't the best idea here.
The end of a HTTP response is defined:
By the final (empty) chunk in case Transfer-Encoding chunked is used.
By reaching the given length if a Content-length header is given and no chunked transfer encoding is used.
By the end of the TCP connection if neither chunked transfer encoding is used not Content-length is given.
In the first two cases you have a well defined end so you can verify that the data were fully received. Only in the last case (end of TCP connection) you don't know if the connection was closed before sending all the data. But usually you get either case 1 or case 2.
To make your life easier, you might want to provide
Connection: close
header when making HTTP request - than web-server will close connection after giving you the full page requested and you will not have to deal with chunks.
It is only a viable option if you only are interested in this single page, and will not request additional resources (script files, images, etc) - in latter case this will be a very inefficient solution for both your app and the server.

Snort rule to verify content of an http request doesnt work

I am trying to verify the contents of the http response to find a content "abbb" in it.So my rule was
alert tcp MY_SERVER HTTP_PORTS -> any any(msg:"The page accessed has content abbb";to_client; established; content:"abb";sid:XXXXX; rev:x;)
unfortunately this rule seems not to work. Can anyone please tell if there is some issue with my rule.
For starters you need to fix the to_client part of the rule as this is not valid syntax. You will need to change this to be:
flow:to_client,established;
You can find more on flow here.
If you are just looking for the content "abbb" sent from your server to the client then you just need a simple content match like you have. I recommend using the fast pattern matcher here to improve the efficiency of the rule. So your content match would look something like:
content:"abbb"; fast_pattern:only;
Putting this together, your rule might look something like:
alert tcp MY_SERVER HTTP_PORTS -> any any(msg:"The page accessed has content abbb";
flow:to_client,established; content:"abbb"; fast_pattern:only; sid:XXXXX; rev:x;)
If this still isn't triggering then there is probably something else going on. Since you are just looking for this in the content you need to check your inspection depth in the http preprocessor. There is a server_flow_depth and a client_flow_depth. Try setting these to 0 (unlimited) and see if your rule is triggering after. For example if you had a client_flow_depth of 300 and the content "abbb" didn't come until after 500 bytes then the rule is never going to trigger because snort isn't configured to inspect that far into the payload.
If you have adaptive profiling enabled then you need to add the metadata service for http otherwise the rule won't match http traffic. This would look something like:
metadata:service http;
If you don't use adaptive profiling then it will use the ports in the rule header.