Tuesday, January 24, 2012

Snort 2.9.2.0: Javascript Normalization

JavaScript obfuscation is an technique being increasingly used to modify the malicious Javascript code and make it difficult for analysis or detection. The latest version of Snort introduced JavaScript normalization capability to enhance Snort's client side detection by decoding obfuscated JavaScript and detecting any malicious code or attacks.

This blog post focuses on how to enable this functionality and write rules on the decoded data.

What are the dependencies/suggestions:
-----------------------------------------------
HTTP Config Options:

The HTTP config option "extended_response_inspection" needs to be turned on for the normalization to work as intended.

Along with this option it is suggested to configure the following options as well.

1. inspect_gzip, which turns on the gzip decompression of HTTP response body
2. normalize_utf, which utf normalizes the HTTP body.

Ex: preprocessor http_inspect_server:
extended_response_inspection \
inspect_gzip \
normalize_utf


Or be sure and use the snort.conf provided here: http://blog.snort.org/2011/12/vrt-snortconf-example-files.html

PAF:

PAF should also be enabled on the HTTP ports. For more information on PAF, see the blog post "What is PAF?" (http://blog.snort.org/2011/09/what-is-paf.html)

How to enable the JavaScript normalization in Snort:
--------------------------------------------------------------
The config option "normalize_javascript" should be added to the HTTP Inspect server configuration to enable normalization. When this option is enabled, Http Inspect searches the HTTP response body (decompressed/de-chunked) for JavaScript by looking at the <script> HTML tags. Snort normalizes the standard JavaScript functions such as unescape/decodeUri/decodeUriComponent/String.fromCharCode, in addition, the %uXXX, %XX, \XX, \uXXXX encoding format is also handled by Snort. Apart from these encodings, Http Inspect will also detect consecutive whitespace and normalize it to a single space. The config option "max_javascript_whitespaces" determines the maximum number of consecutive whitespaces allowed within the Javascript.

Syntax: normalize_javascript

Ex: preprocessor http_inspect_server:
extended_response_inspection \
inspect_gzip \
normalize_utf \
normalize_javascript


Here is an example of the Javascript normalization:

HTTP/1.1 200 OK\r\n
Date: Wed, 29 Jul 2009 13:35:26 GMT\r\n
Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch10 mod_ssl/2.2.3 OpenSSL/0.9.8c\r\n
Last-Modified: Sun, 20 Jan 2008 12:01:21 GMT\r\n
Accept-Ranges: bytes\r\n
Content-Length: 204\r\n
Keep-Alive: timeout=15, max=99\r\n
Connection: Keep-Alive\r\n
Content-Type: application/octet-stream\r\n\r\n
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>FIXME</title>
</head>
<body>
<script>document.write(unescape("%48%65%6C%6C%6F%2C%20%73%6E%6F%72%74%20%74%65%61%6D%21"));
</script>
</body>
</html>

This encoded Javascript results in the following HTTP response body.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>FIXME</title>
</head>
<body>
<script>document.write(Hello, snort team!);
</script>
</body>
</html>


There are three new obfuscation related preprocessor alerts added to Snort.
1. The preprocessor alert with SID 9 and GID 120 is generated when the obfuscation levels within the Http Inspect is equal to or greater than 2.
2. The preprocessor alert with GID 120 and SID 11 is generated when there are more than one type of encodings within the escaped/encoded data.
3. The preprocessor alert with GID 120 and SID 10 is generated When the whitespaces in the javascript obfuscated data is equal to or more than "max_javascript_whitespaces" value preprocessor alert with GID 120 and SID 10 is generated.

Please note, due to the performance constraints we currently decode two Javascript nested obfuscation levels. We are looking into making this a user configurable option in a future release.

How to write rules against the normalized data?
--------------------------------------------------------
You can access the normalized JavaScript buffer using the rule option "file_data" as follows:

Ex:
alert tcp any any -> any any ( msg:"Javascript Obfuscation"; file_data; content:"snort team!"; ..)