Apache DevCenter
oreilly.comSafari Books Online.Conferences.


Pages: 1, 2, 3

Evolution in action

One of the first suggestions that I received for improving Apache::CodeRed came from Randal Schwartz, the well-known Perl author and lecturer. While some people on the mod_perl list thought that Code Red 2 was unlikely to repeat IP addresses, experience made it clear that my computer was being attacked repeatedly from the same computers.

Rather than bombard the same domain administrators with a new note each time my computer was attacked, I used the Cache::Cache module on CPAN (written by DeWitt Clinton) to keep track of which IP addresses I had seen in the last day. Cache::Cache is similar to hashes and DBM files, in that you can associate keys with values. But Cache::Cache keeps track of when you store an item, and automatically expires it after a set amount of time. You can also choose different back-end storage options for Cache::Cache, using the same API with caches in memory and a variety of types of disk files.

By creating a cache with a default expiration time of 86,400 seconds, I could be sure that any IP address stored in the cache would only remain for one day:

my %cache_options = ('default_expires_in' => 86400 );
my $file_cache = new Cache::FileCache(\%cache_options);

Each time Apache::CodeRed receives an incoming request, it stores the IP address in the cache:

$file_cache->set($remote_ip_address, 1);

To determine whether we saw this IP address in the last 24 hours, we simply try to retrieve it from the cache:

my $last_visited = $file_cache->get($remote_ip_address);

If $last_visited is true, then we have seen this IP address recently, and can ignore it.

Another improvement that I made came from David Young, who suggested that we be a bit more selective about which IP addresses are considered dangerous. After all, if I test my Apache::CodeRed installation while my laptop is dialed up to the Internet, should I really end up reporting myself to my ISP?

David's solution was to create @ignore_ip, a list of regular expressions that should be ignored by the system:

my @ignore_ip = ('192\.168\..*', '10\..*');

Before we send e-mail to SecurityFocus, Apache::CodeRed iterates over @ignore_ip, exiting (with a descriptive warning, of course) before we ever send e-mail to SecurityFocus or my ISP's administrators:

foreach my $ignore_ip (@ignore_ip)
if ($remote_ip_address =~ /^$ignore_ip$/) {
$r->warn("CodeRed: Detected known '$remote_ip_address'".
" (matched '$ignore_ip'). Exiting.");


Writing Apache::CodeRed was both fun and interesting, and allowed me to feel like a good Internet citizen while exercising my mod_perl skills on a real-time problem.

At the same time, it demonstrated just how insecure many computers on the Internet are. Moreover, I was appalled to discover how many domains are misconfigured -- at a certain point, the amount of bounced e-mail I received from domains that had failed to configure "postmaster" accounts was so great that I collected it into a file rather than let it clog my in-box.

What's most amazing is that more than a week after Code Red 2 hit the Internet, my servers continue to get pounded by requests for /default.ida. True, the requests are now coming every 30 minutes, rather than once every 3 to 4 minutes -- but it means that there are still lots of uninformed system administrators out there, as well as a lot of infected, vulnerable computers.

Reuven M. Lerner is a Web/database consultant and a columnist for Linux Journal.

Return to the Apache DevCenter.

Sponsored by: