Code Red is a pain even for Apache administrators. It takes up time and space even to send a 404. Wouldn't it be nice to be able to help alleviate the problem rather than just trying to bear it? Countermeasures? You bet, here's how to do it with PHP and bash (and note that this could easily be adapted to whatever you regularly employ, perl, jsp, etc.) The following is an explanation of the solution with source code and explicit instructions included below (PHP and bash).
First off let me explain the premise. My goals are not to be malicious and to waste even more space and time dealing with the problem (ie, don't kill the offending server and the solution needs to have less overhead than a 404 or it there is no sense in doing it).
I use PHP regularly so I decided to employ it again in this case to catch the "default.ida" requests (which for the uninitiated are what CodeRed requests) and then pass them to a shell script to "deal" with them (again, this could be done with any server side language). This first part is trivial. Simply edit the apache httpd.conf file to add a type (AddType) for the .ida files to establish this extension as a php mime type alias. Here is an example:
That starts PHP accepting the .ida files. Now create the aforementioned "default.ida" file that CodeRed so enthusiastically requests. Within that file, now a PHP script in my case, record the IP address of the request (the offending CodeRed host). Then store that IP address in a file for later use by a shell script. This is really easy to do (it's a tad bit more involved than is explained here, the file needs to not have duplicate addresses, permissions need to be set, etc, but it still qualifies as easy).
Once the file is there and is being updated by a web server script (PHP) to record offending IP addresses, then the next step is that that file need simply be parsed by a shell script to block the offenders. In my case, I prefer just to use ipchains and DENY any future requests from those hosts at that level (ipfilter could also be used very easily). This approach is not malicious (as the goals state) and is exponentially beneficial as more offending hosts are added requests from those hosts obviously never make it to the webserver again (and this satisfies the second goal, less effort than a 404).
This shell script is also fairly simple. It parses the aforementioned offending hosts file and adds an ipchains INPUT rule to deny any future requests from those hosts. This script also does a little housework in that it deletes, recreates and sets permissions on the offending hosts file.
The final part in the countermeasure is to automate the parsing of the file via the shell script. This is simply done with cron. It's again easy to setup and tell the file to run once every hour (or whatever interval you choose). This way your webserver is automatically recording the IP addresses of the offenders to a file and your server is automatically running a shell script that blocks the offending hosts.
This works well, I have employed it for some time and CodeRed requests do still come in but they have certainly diminished a great deal (and yes, this is due in part to other sysadmins cleaning up the CodeRed messes, but also to the fact that offending hosts keep offending and each one that is removed shall never strike again).
Also note that YES, as you may have observed, this countermeasure does drop access from the offending hosts to your webserver permanently. You may choose to reset this and re-allow access at some point in the future (very easy to do with ipchains), but personally I dont worry too much about that. The offending IPs are Microsoft webservers and while they could also be used as someone's workstations, I am not really troubled by stopping their access to my webserver altogether. After all, the benefit of performance for all the non offending users far outweighs the access rights of the offenders themselves (IMHO).
USE AT YOUR OWN RISK, No WARRANTY, BLAH BLAH BLAH
UPDATE: Several observant readers have pointed out in the phorum that you could do this without PHP. The requests are also logged in the apache error log and you could simply parse that. Those are valid points and certainly worth consideration. I chose PHP because it was easy and gets the job done adequately. Its true that a simple shell script (especially the "one liner" in the phorum) would be more efficient since PHP would not even have to be invoked.
ALSO Be advised that when using this setup (either way, PHP or not) a DoS attack is possible if the source address is spoofed. Make sure that the variable used to determine the source address really is the source address (that way DoS attackers can only eliminate themselves, and personally, I am OK with that). Do this by ensuring that by the time a packet hits your webserver its source is not spoofed (see ipchains howto, or whatever your firewall is, is to setup ip spoofing protection).
Source Code (also available as tar download via link)
PHP script (default.ida)
# copyLeft totsp.com
# charlie collins
# temple of the screaming penguin
# http://screaming-penguin.com
# 08.15.2001
# this is a script to record the ip addresses of CodeRed offenders to a file
# (actually this script gets all requests for 'default.ida', legitimate or not)
# this PHP file is intended to be used in CONJUNCTION with a shell script and cron job
#
# the shell script then reads the ip addresses from the file and drops them via ipchains (and deletes and recreates the file)
# the idea here is that php listens in the default.ida file and records the ip address of hosts that request it to a file
# then a shell script reads the recorded ip addresses from said file and drops any future requests using ipchains
# a cron job is used to call the shell script periodically
# REQUIRED COMPONENTS
# default.ida, PHP script to record ip addresses of those requesting it (THIS FILE)
# coderedhosts.txt, file used by this script to store ip addresses
# killCodeRed.sh, bash script to process the file with ip addresses, drop using ipchains and delete + recreate file
# SETUP INSTRUCTIONS ***
# the entire process requires 6 parts to setup (and uses php, bash, ipchains and cron, could easily be adapted to other stuff, ie netfilter)
# 1 - modify httpd.conf so that .ida files are processed by PHP (AddType application/x-httpd-php .ida) AND restart apache
# 2 - install this file in the apache docroot, make sure it is named 'default.ida'
# 3 - install accompanying bash shell script 'killCodeRed.sh' (preferably NOT in the docroot, wherever you want) and ensure root user has x perms
# 4 - set variables in 'killCodeRed.sh' to match machine stuff (EXTERNAL_ADDRESS, IPCHAINS, etc)
# 5 - as root RUN the ./killCodeRed.sh script once BEFORE proceeding (it deletes the coderedhosts.txt file if present and recreates it)
# 6 - add cron job to run killCodeRed.sh at desired interval (hourly, etc) (see the cron man pages for cron help)
## SECURITY NOTES
# run the webserver as a non priveleged user (duh), ie nobody
# do NOT grant PHP permissions to CREATE files in the docroot (the killCodeRed.sh script will create the file, dont let PHP do it)
# make sure that the web server user can WRITE to the coderedhosts.txt file (that file only, and again, not the entire DIR)
# this is just present to test this file and make sure it flies and send something to response
echo "remote address = $REMOTE_ADDR";
# define the file
$codeRedHostsFile = "/usr/local/apache/htdocs/coderedhosts.txt"; #edit to match apache docroot
# open the file for read(permissions must obviously be correct)
$fp = fopen($codeRedHostsFile, "r");
# then check to file to make sure this host is not already in it
$stringCodeRedHostsFile = fread($fp, filesize($codeRedHostsFile));
if(!ereg("$REMOTE_ADDR",$stringCodeRedHostsFile))
{
# if the host is not in it, the reopen the file, pointer at the end, and write to it
$fp = fopen($codeRedHostsFile, "a");
fwrite($fp, "$REMOTE_ADDR \n");
}
# close the file
fclose($fp);
?>
BASH script (killCodeRed.sh)
#!/bin/bash
# killCodeRed.sh
#
# copyleft totsp 2001
# charlie collins
# temple of the screaming penguin
# http://screaming-penguin.com
# this script is used in CONJUNCTION with a file of ip addresses
# the ip addressed represent hosts known to be infected with codeRed
# this script then drops connectivity to those hosts via ipchains
# (the file of ip addresses can be automatically generated, ie PHP, perl, etc )
# setup ultra simple vars (CUSTOMIZE HERE)
EXTERNAL_INTERFACE="ethX" # you must edit this
CODEREDHOSTSFILE="/usr/local/apache/htdocs/coderedhosts.txt" #edit this as required (if apache docroot is different)
IPCHAINS="/sbin/ipchains"
GREP_PARAM="^[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*"
FILEOWNER="nobody" # edit this to match webserver user
# parse the file
for i in $( grep $GREP_PARAM $CODEREDHOSTSFILE )
do
echo "Deny access to host: $i"
$IPCHAINS -A input -i $EXTERNAL_INTERFACE -s $i -j DENY
done
# then remove, recreate and set perms on file
# this is to keep the file lean and still ensure that it DOES exist
rm -rf $CODEREDHOSTSFILE
>$CODEREDHOSTSFILE
chown $FILEOWNER $CODEREDHOSTSFILE
chmod u+w $CODEREDHOSTSFILE
Comments
Re: Apache CodeRed Countermeasures
This looks as if it could be handy.
Unforch, the links mentioned don't seem to be visible
to mozilla 9.3.
I'm also not familiar with your site, so a roadmap would
be appreciated.
Cheers, Gene
Re: Apache CodeRed Countermeasures
You can do without the PHP. Apache rejects (404) all code red attacks and logs then in /var/log/httpd/access_log. I have a perl script that scans this log for code red attacks. (I am putting them into a MySQL database for analysis.) Here is a perl script that can be used to generate a list of unique ip addresses that have attacked your system with code red:
==============================================================
#!/usr/bin/perl -w
#
# parse access_log for code red ip addresses
#
use strict;
# The http access log
my $acclog="/var/log/httpd/access_log";
# read log file, identify code red attack entries
open (ACCLOG, $acclog ) or die "Can't open $acclog: $!n";
my @ip_list;
LINE: while ( my $line= ) {
# keep only attack entries
if ( $line =~ m/default[.]ida/i or
$line =~ m/NULL[.]idsa/i or
$line =~ m/xxxxxxxxxx/i or
$line =~ m/aaaaaaaaaa/i or
$line =~ m/nnnnnnnnnn/i ) {
my ($ip, $rest) = split / /,$line;
push @ip_list, $ip;
}
}
# sort them, print out unique entries
@ip_list=sort @ip_list;
my $ip_last="none so far";
foreach my $ip (@ip_list) {
if ($ip ne $ip_last) {
$ip_last=$ip;
print "$ipn";
}
}
exit(0);
==============================================================
Nice idea but there is a flaw.
Alot of the Code Red I have been seeing, and other people, (The Article on Code Red Earlier in Linux Today) has been from home users who installed thing like Frontpage, which comes with a chopped down IIS server. Thus those people might latter on want to view your webpage, and now cannot. Also there is a firewall potential here too. If the offending machine was a windows "firewall" or Internet Sharing system, all behind the "firewall" are now blocked. Just a few things to remember.
Chris Brandstetter
Re: Apache CodeRed Countermeasures
Someone pointed out a problem with the script. It seems that posting it to this site corrupted a line. The line that reads:
LINE: while ( my $line= ) {
should look more like:
LINE: while ( my $line= <ACCLOG> ) {
I hope that comes through OK. The text "ACCLOG" should have angle brackets around it (i.e. less-than and greater-than signs).
Also, the code's indentations were lost.
Re: Apache CodeRed Countermeasures
yes sir, nice, thanks. i thought about doing it the same way, just parsing the apache log, but I didnt even want the requsts to get that far (of course, splitting hairs, but the php method was simply more accessible and handy to me, but again, good stuff)
Re: Nice idea but there is a flaw.
valid points sir, and I actually address that and my logic for BLOCKING THEM ANYWAY in my article. this is not a "flaw", its a decision that anybody whom uses this will have to make.
Re: Apache CodeRed Countermeasures
sorry about that, the forum (phorum) strips potentially malicious tags and sometimes doesnt do a great job of determining what is and is not dangerous. if you want to email me the script, i will post a full story on it on the front page (or you can create an ID and do so yourself, note that the storyposting system also strips tags, the ampergt; and amperlt; will have to be used.)
Re: Apache CodeRed Countermeasures
sorry, i dont understand what the issues are. i use mozilla, i posted the story with mozilla, it all works fine in mozilla (i also use 0.93.) all info that should be needed is in the story and the scripts.
Re: Apache CodeRed Countermeasures
this oneliner does the same:
grep "GET /default.ida?XXX" access.log |cut -f1 -d' '|sort|uniq
wc -l on this gives me 324 unique hosts to block.
re: php logging
why store them seperately when the log file already keeps it?
just cron log it and merge it with the ipchain blocked hosts.
Re: Nice idea but there is a flaw.
The simple answer to this "Flaw" would be to delete the file after a set period of time - i.e 24 hours- so that the offenders are only blocked for a maximum of 24 hours.
The best solution (IMHO) is a storing a timestamp for each server and firewalling each one for a set period.
Of course as atrox said, this is a site by site decision to make...
Edwazere
Re: Apache CodeRed Countermeasures
thanks, your solution is very efficient (and admittedly better than the PHP flavor.) the only reason i php'd it at all was that i made a decision up front to not try to mess with the apache log file. why? because i wanted the server to respond to the requests rather than 404 and therefore not put the monster default.ida message in the log. i started there and then ended up simply expanding to block the hosts. again, splitting hairs, my solution is pretty darn simple, yours is more elegant (one line, shell script.)
Re: Apache CodeRed Countermeasures
Yes, That is simpler.
What I posted was extracted from a larger script that also tracked timestamps from the log and fed all the data to a MySQL database for analysis so a quick one-liner wasn't appropriate.
Also I found that not all attacks were well-formed. Some didn't even show the "default.ida' but I could recognize them from other pieces of the data. So, I checked several signatures. This could be added to your one-liner, but then it would start to get a little complicated (still relatively short).
Re: Apache CodeRed Countermeasures
That's very strange but each time I try to run manualy the killCodeRed.sh (as root) it always answers "/bin/killCodeRed.sh: No such file or directory" I checked if I installed it correctly, if vars were correctly set, everything is ok... except that it doesn't run... why (I run Linux-Mandrake 7.2)
Could you help me ?
Re: Apache CodeRed Countermeasures
that's the script solution, seperated into init step and cronjob.
cd /var/log/httpd
init:
# initially block code red hosts
grep "GET /default.ida?XXX" access.log |cut -f1 -d' '|sort|uniq >codered.init
for i in $(cat codered.init); do
/sbin/ipchains -A input -j DENY -i eth0 -s $i
done
echo "`wc -l codered.init` hosts blocked"
cron:
# check for new hosts regularly
grep "GET /default.ida?XXX" access.log |cut -f1 -d' '|sort|uniq >codered.new
for i in $(cat codered.new); do
if [ ! $(grep $i codered.init) ]; then
/sbin/ipchains -A input -j DENY -i eth0 -s $i
echo $i >> codered.init
fi
done
to actually know if the poor user reacted on that, I redirected /default.ida to a huge mp3 file of mine, which is streamed over icecast. this stream lasts for one hour. in the icecast logs I can see when or if the user stopped that streaming manually.
it should hurt the user to force him to download an antivirus toolkit and i don't have to pay for traffic :)
if he stopped it and if afterwards no /default.ida appears,
he is revoked immediately. all other stay blocked for 2 weeks.
I'll have to beautify this icecast analysis-and-revoke script and post it then.
note that that large number of ipchains slows down network ins. so it should not be blocked forever. but such worms typically last for two weeks. code-red lasts longer, but it will
decrease soon.
Re: Nice idea but there is a flaw.
For companies facing hundreds of thousands of attempts a day on a multitude of IP addresses, it makes more since to have it build and deny based on an interval. For instance, at the company I work for, the new IPs for banning are grabbed, sorted, and uniq'd around every hour. Then based on the number of attemps and a few other delimiting characteristics, they're disallowed for a possible one up to [x]num of days.
-tre
http://piclabs.com
Re: Apache CodeRed Countermeasures
In addition to doing something similar (on Win98 /Apache), I also have a php script that finds the owner of the domain on Arin whois and sends the domain contact an email automatically, requesting their assistance in getting the offender corrected. What is the conscensus as to whether this is effective? I have noticed that several addresses no longer attack, but that could probably be coincedence also. TIA.
Re: Apache CodeRed Countermeasures
i think the arin-email idea is great. however i would use it cautiously because it of course means more overhead for you. in an ideal situation notifying the offending host would be diplomatic and very helpful, but if you are getting 3000 code red "visitors" an hour, it would consume too many resources.
gladly the whole thing is dying down but i would keep the scripts handy for the next offender (which unfortunately is all too likely.)
Re: Apache CodeRed Countermeasures
OK< I looked at this article code, and basically used bits and bobs to build up my IPCHAINS rules on certain consistant offending machines I keep getting attacked with... but IPCHAINS doesn't work??
My set-up is basically eth0 internal network, eth1 external interface, with Apache running on that machine. My firewall works, as i have all ports below 1024 closed, and a lot above that.
Why is this? My mate remarked "You now, it's [HTTPD] linked onto the transport layer before IPChains is".
Thanks,
Nick
Re: Apache CodeRed Countermeasures
hmmmm
the code in these examples receives the HTTP request the first time, records the ip address, and THEN blocks it based on the IP. what this does is it blocks the next request from said host BEFORE it even gets to the webserver. the issue isnt the network layers.
ipchains examines all the packets before they are allowed or disallowed and passed on to subsequent services, its using the network layer and is certainly in front the transport layer.
you say "your firewall works", i dont know what might be wrong, but just make sure you are blocking the offending hosts the same way the other stuff is blocked (ie use whats working)
Re: Apache CodeRed Countermeasures
Another short oneliner to count hits per day (just to teach some unix basics :)
maybe for your date format you'll have to tweak it but you
get the idea. with awk it would be easier of course.
tv:/var/log/httpd # grep "GET /default.ida?XXX" access.log |cut -f1,4 -d' '|cut -f1,2 -d'/'|sort -mb -t' '|uniq -c -f1
9 193.90.2.17 [04/Aug
96 193.171.149.30 [05/Aug
150 cevre.cu.edu.tr [06/Aug
193 193.133.13.215 [07/Aug
188 212.93.133.21 [08/Aug
123 193-152-185-156.uc.nombres.ttd.es [09/Aug
105 193.95.79.154 [10/Aug
76 193.171.150.237 [11/Aug
81 211.99.208.130 [12/Aug
54 193.171.7.35 [13/Aug
61 193.171.249.90 [14/Aug
67 d163037.lsb.pt.kpnqwest.net [15/Aug
103 193.171.150.237 [16/Aug
66 193.171.149.30 [17/Aug
42 193.171.50.156 [18/Aug
10 61.182.241.111 [19/Aug
11 193.95.105.179 [20/Aug
26 aste-genev-bois-102-1-1-167.abo.wanadoo.fr [21/Aug
17 e-188.vc-graz.ac.at [22/Aug
23 archlars.nic.it [23/Aug
50 aneuilly-101-1-4-61.abo.wanadoo.fr [24/Aug
7 amontpellier-201-1-4-75.abo.wanadoo.fr [25/Aug
10 193.67.81.97 [26/Aug
7 193.105.44.190 [27/Aug
10 193.15.188.4 [28/Aug
This curve persuaded me to turn it off a few days (25/Aug).
The IP is the first hit per day. only the number (count/day) is interesting.
Re: Apache CodeRed Countermeasures
Oops. Forgot to mention that these numbers are WITH the ipchains blocking. So the real hits are much higher, the curve is much steeper. This is just the number of not yet blocked IP's.
At Aug 25 I turned off ipchains blocking and the global
hitrate didn't went up. It keeps going down.
Maybe a router in between is blocking them now :)
Re: Apache CodeRed Countermeasures
thanks again, this is great stuff and while it may be "basics" to some, i assure you its not that elementary to most folks, even unix folks. this is quick and consise work with the shell tools, again, good stuff.
Re: Apache CodeRed Countermeasures
This works well - Thank you!
I actually had to add a second cut to get it to work on our server:
grep "GET /default.ida" /var/log/httpd/access_lo* |cut -f1 -d' '|cut -f2 -d':'|sort|uniq >codered.init
Question:
I'm new to this stuff. Just slowly figuring out the scripting, but I don't know too much about these IP Chains. How do you now re-allow someone 2 weeks later? Are you doing this automatically through the cron job?