Summary
-------
There is a serious security bug in wu-ftpd v2.4 (including the
version from Academ) which may allow both regular and anonymous users
to access files as uid 0 (root). The same bug is also responsible for
an advisory lock not being unlocked - potentially resulting in blocked
access to future ftp logins and filling up the process table and swap
space until the server dies.
Description
-----------
The ftpd server installs two signal handlers as part of its startup
procedure: one to catch SIGPIPE for control/data port connection closes,
and one to catch SIGURG for when out-of-band signaling is used with the
ABOR (abort file transfer) command. The SIGPIPE handler is:
lostconn(int sig)
{
if (debug)
syslog(LOG_DEBUG, "lost connection to %s [%s]", remotehost, remoteaddr);
dologout(-1);
}
...which causes the ftpd server to exit via dologout() whenever the
control or data connection is unexpectedly closed. The function
dologout() is:
dologout(int status)
{
if (logged_in) {
(void) seteuid((uid_t) 0);
logwtmp(ttyline, "", "");
}
syslog(LOG_INFO, "FTP session closed");
if (xferlog)
close(xferlog);
acl_remove();
/* beware of flushing buffers after a SIGPIPE */
_exit(status);
}
...which changes the effective uid to 0, adds a logout record to wtmp,
closes the xferlog log file, removes this instance of the server from
the PID file for his class, and exits.
The initial part of the SIGURG handler is:
myoob(int sig)
{
char *cp;
/* only process if transfer occurring */
if (!transflag)
return;
cp = tmpline;
if (getline(cp, 7, stdin) == NULL) {
reply(221, "You could at least say goodbye.");
dologout(0);
}
upper(cp);
if (strcmp(cp, "ABOR\r\n") == 0) {
tmpline[0] = '\0';
reply(426, "Transfer aborted. Data connection closed.");
reply(226, "Abort successful");
longjmp(urgcatch, 1);
}
(...)
...which does nothing if transflag is 0 - not currently doing a file
transfer, but if you are and an ABOR command was issued along with the
"urgent" data that caused this signal, then the procedure does a longjmp()
restoring the "urgcatch" saved state, which ultimately returns back to the
server main command loop.
Now, some FTP client programs will abort a file transfer by BOTH
closing the data connection AND issuing an ABOR with out-of-band signaling.
In many instances, the ftpd server gets the SIGPIPE due to the closed data
connection and begins the dologout() procedure. While it is uid 0 and
sometimes while it also has the pid file advisory lock (which occurs in
the acl_remove() procedure), the ftpd server will sometimes be interrupted
by the SIGURG that is delivered as part of the ABOR command. Since
transflag is not 0 (a file transfer WAS occuring), the signal handler does
a longjmp which ultimately returns to the main command loop...and presto,
you are uid 0, and to make things even better, the xferlog log file is
closed so nothing you do is even logged.
A patch to fix this problem is simple:
*** ftpd.c.bak Wed Jan 1 22:10:05 1997
--- ftpd.c Wed Jan 1 22:10:14 1997
***************
*** 2503,2508 ****
--- 2503,2514 ----
void
dologout(int status)
{
+ /*
+ * Prevent reception of SIGURG from resulting in a resumption
+ * back to the main program loop.
+ */
+ transflag = 0;
+
if (logged_in) {
(void) seteuid((uid_t) 0);
logwtmp(ttyline, "", "");
...which does as the comment suggests.
-DG
David Greenman
Core-team/Principal Architect, The FreeBSD Project
[ wuftpd-questions | wuftpd-announce | wuftpd-dev | wuftpd-doc | wu-ftpd | wu-ftpd.org | Resource Center ]