Apache::CodeRed
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.");
return FORBIDDEN;
}
}
Conclusion
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.
