Date: Tue, 23 Feb 1999 14:59:14 -0400 From: Julien Nadeau To: PacketStorm@genocide2600.com Subject: NcFTPd remote buffer overflow Proof of Concept - Security Advisory 02/23/99 http://poc.csoft.net Released by poc@csoft.net sw3wn@poc.csoft.net --- Affected Program NcFTPd Description FTP server (commercial) Severity Theoretical root compromise, logs compromise Synopsis: 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). Problem: 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 =p). 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. Like with most buffer overflows there are probably work-arounds to exploit it - this could have been a particulary neat exploit, since it runs as a child and one could gain access transparently without crashing the parent. 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. A few minor DoS attacks are possible but, who cares. Oh and this could be used to not get listed in the logs too. 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:$ -- Status: I contacted the authors, nice enough to send me back the piece of code that causes the problem - here goes: 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); for ( ; ; ) { c = *cp++; if (c == '\0') break; if (! isdigit(c)) c = ' '; if (dst < dstlim) *dst++ = c; } *dst = '\0'; if (sscanf(buf, "%u%u%u%u%u%u", &octets[0], &octets[1], &octets[2], &octets[3], &octets[4], &octets[5] ) != 6) { return (-1); } for (i=0; i<6; i++) { if (octets[i] > 0xFF) return (-1); } sinaddr->sin_family = AF_INET; u = (octets[0] << 24) | (octets[1] << 16) | (octets[2] << 8) | (octets[3]); sinaddr->sin_addr.s_addr = htonl(u); u = (octets[4] << 8) | (octets[5]); sinaddr->sin_port = htons((unsigned short) u); return (0); } /* ftp_aton */ void Port(char *line) { if (gLoggedIn == 0) { NotLoggedIn(); return; } if (gAllowPORT == 0) { Reply("550 This site does not permit PORT. Please use PASV instead.\r\n"); return; } if (ftp_aton(line, &gRemoteDataAddr) < 0) { Reply("501 Syntax error in parameters.\r\n"); return; } /* ... */ }