COMMAND
Apache httpd
SYSTEMS AFFECTED
Systems running Apache 1.2.x (up to .5) and earlier (?)
PROBLEM
Jan Wedekind discoverd a DoS attack in Apache and (eventually)
other / all (?) httpd's (thanks to Bernard "sendmail" Steiner).
For apache 1.2.x (and very sure all versions before), the DoS may
be exploited if both of the following conditions are true:
- the intruder has (at least FTP) write access to (at least)
one HTML directory
- per directory access (AccessFileName configuration
directive) is enabled and the filename is known to the
intruder (default is .htaccess)
This configuration will be found very often at private homepages
with FTP-Upload accounts. Now just put a new .htaccess file to
the Server with the following contents:
AuthType Basic
AuthName DoS Attack
AuthUserFile /dev/zero
<Limit GET POST>
order deny,allow
allow from all
require valid-user
</Limit>
If you're now trying to open this directory (or any file within)
and enter any user / password combination, you'll get a hanging
(death running) client. This is, because it's reading /dev/zero
and searches for a colon (':') to separate the user name from the
password field (mod_auth.c, get_pw(), line 127). Now the intruder
may stop this request in the browser (the server client process
will still continue) and start a new one. The next client will be
forced to read /dev/zero. Repeat this, until 'MaxClient' will be
reached. Not only this server will stop to work (e.g. the parent
will wait for all further requests for any of it's child), but
also the machine will going almost to hang with a CPU load of
about MaxClient.
SOLUTION
One workaround is to disable .htaccess in srm.conf by commenting
out AccessFileName (default is NULL in the apache distribution,
e.g. disabled):
#AccessFileName .htaccess
Another workaround is patch apache source because also other
authentication methods may be exploitable you may prefer to patch
it in a way that it's no longer be available to open /dev/zero
(or any other device) for reading, so Jan patched fpopen() in
alloc.c:
kirk: ~/src/apache_1.2.4/src> gdiff -uw alloc.c.orig alloc.c
--- alloc.c.orig Thu Jan 8 14:14:13 1998
+++ alloc.c Fri Jan 9 13:37:21 1998
@@ -839,9 +839,14 @@
{
FILE *fd = NULL;
int baseFlag, desc;
+ struct stat buf;
block_alarms();
+ if ( *mode != 'r'
+ || (strcmp(name,"/dev/null") == 0)
+ || stat(name, &buf) == 0 && ((buf.st_mode & S_IFMT) == S_IFREG))
+ {
if (*mode == 'a') {
/* Work around faulty implementations of fopen */
baseFlag = (*(mode+1) == '+') ? O_RDWR : O_WRONLY;
@@ -854,6 +859,7 @@
} else {
fd = fopen(name, mode);
}
+ }
if (fd != NULL) note_cleanups_for_file (a, fd);
unblock_alarms();