Apache DevCenter
oreilly.comSafari Books Online.Conferences.



by Reuven M. Lerner

Like many programmers and system administrators, I like to know when something goes wrong with my web site, no matter how trivial the problem is. So when I moved my company's web server to mod_perl and HTML::Mason last year, one of the first things I did was write an automatic warning system to send me an e-mail message whenever a visitor encounters a broken link.

I usually expect to receive two or three such e-mail messages on any given day, with the majority coming from people who enter wrong URLs. But on the night of Saturday, August 4, I had hundreds of automatically generated "broken link" reports in my in-box, all of which came from requests for /default.ida. It didn't take long to figure out that my server was under attack by the Code Red 2 worm.

Code Red 2, in case you haven't heard, attacks Windows 2000 systems running Microsoft's IIS Web server. The worm enters via a very long HTTP request beginning with /default.ida. Once it has infected a system, the worm opens some security holes, and then begins trying to spread to other servers. The worm mostly attacks computers whose IP addresses are similar to that of its current host, but sometimes it chooses a new IP address at random.

Code Red 2 never should have infected more than a few dozen computers. A patch has been available from the Microsoft web site for some time, and the headlines that the original Code Red worm generated should have been enough to alert even the sleepiest system administrator. The unfortunate reality is that many system administrators, including those running Microsoft's own Hotmail system, didn't patch their systems in time, and were infected by this fast-spreading threat.

My own server wasn't vulnerable to these attacks, because it runs Apache and Linux. But Code Red 2 didn't check a server's identity when launching an attack; it sent the dangerous HTTP request to anyone who would listen, betting on the large number of IIS servers on the Internet. While I didn't have to worry about infection, I felt like I should do something to let people know that their computers had been infected.

My solution was to write a small module for mod_perl, originally called "CodeRed" and eventually renamed Apache::CodeRed. The module's job is to intercept any request for /default.ida, determine the host name of the HTTP client, and send a warning e-mail message to the administrator of that client.

Within a day of posting the first version of Apache::CodeRed on the mod_perl e-mail list, I began to get feedback, patches, and suggested improvements. I added a cache of IP addresses, to ensure that each system administrator would receive only one warning in a given 24-hour period. I sent e-mail to the designated address at SecurityFocus.com, which was keeping track of such things. And I added a list of IP addresses for which warnings were unnecessary, avoiding the embarrassing situation of turning a simple test into a false warning of a Code Red 2 infection on a Unix system.

A quick primer on mod_perl

Writing Apache Modules with Perl and CWriting Apache Modules with Perl and C
By Lincoln Stein & Doug MacEachern
1st Edition March 1999
1-56592-567-X, Order Number: 567X
743 pages, $39.95

Before looking at Apache::CodeRed, let's review how mod_perl works. The goal of Apache, like any Web server, is to produce an HTTP response for each incoming HTTP request. When Apache gets a request for foo.html, it will normally return the file verbatim. When it gets a request for foo.shtml in a directory that has been marked for server-side includes, it will execute each of those server-side includes, and then return the resulting file. And when it receives a request for foo.pl in a directory marked for CGI programs, Apache will execute the program, returning the program's output to the user's browser. Each of these behaviors is controlled by a different "handler." By assigning a handler to a directory (or to the files in a directory), you change the way Apache behaves.

Mod_perl lets us go one step further by writing our own handlers that can be attached to files, directories, or URLs. We do this by telling Apache that mod_perl will be handling things, and then by telling mod_perl which specific Perl module should handle the HTTP request. By default, mod_perl looks for a subroutine named "handler" in the named module.

After I wrote and installed Apache::CodeRed, I attached it to the URL /default.ida by inserting the following into my Apache configuration file, generally named httpd.conf:

<Location /default.ida>
SetHandler perl-script
PerlHandler Apache::CodeRed

The above tells Apache that when an incoming HTTP request asks for /default.ida. The response should be generated by the Perl subroutine Apache::CodeRed::handler.

Our handler receives one input, an instance of the Apache request/response object traditionally called $r. It will also have to return a value to its caller, indicating whether it handled the request (OK), is passing the buck to another handler (DECLINED), or refuses to allow access to the requested URL (FORBIDDEN). Remember that these constants, which are defined in the module Apache::Constants, are not HTTP response codes, but rather indications of whether Apache may return an HTTP response to the user.

Let's look through the overall logic of the code rather than a line-by-line analysis. You'll notice that I often use the $r->warn method, which sends a warning to the Apache error log. Chatty warnings in the error log allowed me to easily keep track of what was happening, which is often a good idea when working on server-side applications. I used $r->warn, rather than $r->log_error to allow Apache administrators to turn off the chattiness by modifying httpd.conf, rather than the module.

Pages: 1, 2, 3

Next Pagearrow

Sponsored by: