WU-ftpd Upload Ownership/Permissions Bug

Michael Brennen (mbrennen@FNI.COM)
Tue, 24 Jun 1997 10:39:44 -0500

After looking further into the wu-ftpd bug I reported last week, I
realized that many sites may not be vulnerable to the bug that I reported.

In retrospect I realized that I had recently added the /./ to the end of
the anonymous ftp path in /etc/passwd while rearranging the ftp user. I
certainly had no idea that it would break the upload directive code and
found it quite by accident. The code does not expect /./ at the end of
the anonymous ftp path and does not behave correctly if it exists.

The argument could be made that the /./ should never [need to] be on the
anonymous ftp path since it is always chrooted. Given the unexpected
consequences of placing it there, and that adding the patch does not alter
functionality if /./ is not there, I would argue that the source change
should be made in the eventuality that someone puts /./ on their anon ftp
path.

anonymous is a chrooted account, and it would be easy to think you needed
the /./. If /./ is added, it unexpectedly changes the behaviour of the
daemon for the worse. That hole should be closed.

A better patch against the original source is below; reverse the first
before applying this one.

-- Michael

--- ftpd.c.orig Wed May 21 09:29:17 1997
+++ ftpd.c Fri Jun 20 11:19:01 1997
@@ -1550,6 +1550,8 @@
expand_id();

if (anonymous || guest) {
+ char *sp;
+
/* We MUST do a chdir() after the chroot. Otherwise the old current
* directory will be accessible as "." outside the new root! */
#ifdef VIRTUAL
@@ -1559,28 +1561,19 @@
pw->pw_dir = sgetsave(virtual_root);
}
#endif
- if (anonymous) {
+ /* determine root and home directory */
+
+ if ((sp = strstr(pw->pw_dir, "/./")) == NULL) {
if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
reply(550, "Can't set guest privileges.");
goto bad;
}
- } else if (guest) {
- char *sp;
-
- /* determine root and home directory */
+ } else {
+ *sp++ = '\0';

- if ((sp = strstr(pw->pw_dir, "/./")) == NULL) {
- if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
- reply(550, "Can't set guest privileges.");
- goto bad;
- }
- } else {
- *sp++ = '\0';
-
- if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
- reply(550, "Can't set guest privileges.");
- goto bad;
- }
+ if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
+ reply(550, "Can't set guest privileges.");
+ goto bad;
}
}
}