COMMAND
ncftpd
SYSTEMS AFFECTED
Linux
PROBLEM
Following is based on "Proof of Concept" Security Advisory.
NcFTPd is a commercial FTP (File Transfer Protocol) server, in the
NcFTP product line. The source code is not publicly released.
This was tested on Linux with libc5 (there's a glibc2 specific
version available). NcFTPd's PORT parsing function has a stack
buffer overflow problem, which would basically allow a user to
remotely execute arbitrary code - the thing here is that the PORT
parsing function seem to change characters, that are not in the
range 0x30-0x39 (ASCII '0'-'9'), into 0x20 (ASCII space), hence
making an exploit almost impossible (note that, if ascii 0x40
would be allowed that would be a different story). The program
only parses for characters out of the 0-9 range in a specific area
in memory (the one that contains return address heh) - the rest
is kept unchanged, and you can't really go further in memory,
input line size is restricted.
The current bug is not really a problem, it can crash the child
process with a segfault, the parent process receives a signal 6
(abort) and the child process stay zombie for a few seconds and a
brand new one is created. Example:
evil:$ nc victim ftp
220 victim NcFTPd Server (unregistered copy) ready.
user anonymous
331 Guest login ok, send your complete e-mail address as password.
pass some@thing
230-You are user #1 of 50 simultaneous users allowed.
230-
230 Logged in anonymously.
port 00000000000000000000000000000000000000000000 (...)
501 Syntax error in parameters.
evil:$
So, this can occur if an attacker uses 64 or more characters in
the range of '0' to '9' in an FTP "PORT" command. This can cause
the child process handling the FTP connection to crash and
respawn, but does not leave an attacker with root privileges. For
reference, here is a snippet which illustrates the actual problem:
static int
ftp_aton(const char *cp, struct sockaddr_in *sinaddr)
{
char buf[64];
char *dst;
char *dstlim;
int i, c;
unsigned int octets[6], u;
memset(sinaddr, 0, sizeof(struct sockaddr_in));
dst = buf;
- dstlim = dst + sizeof(buf);
+ dstlim = dst + sizeof(buf) - 1;
for ( ; ; ) {
c = (int) *cp++;
if (c == '\0')
break;
if (! isdigit(c))
c = ' ';
if (dst < dstlim)
*dst++ = c;
}
*dst = '\0';
SOLUTION
NcFTPd 2.4.1 is available which fixes this problem.