COMMAND
wu-ftpd
SYSTEMS AFFECTED
Systems running wu-ftpd beta 13
PROBLEM
Note that many sites may not be vulnerable to this bug. It works
only if you had added the /./ to the end of the anonymous ftp
path in /etc/passwd while rearranging the ftp user. The code
does not expect /./ at the end of the anonymous ftp path and does
not behave correctly if it exists.
There is a potentially serious bug in ftpd.c in wu-ftpd beta 13.
During anonymous login, the /./ is not clipped off the struct
passwd pw->pw_dir field that is saved as the chroot directory in
ftpd.c.
Because the /./ is still on the end of the pw->pw_dir field,
upl_check() 'upload' directive processing will fail in
extensions.c because the file name paths will not compare. It is
highly unlikely that the upload directive root path would also
have the /./ on the end.
If upload directive processing fails for the anonymous user,
sites that depend on upload directives to properly set incoming
file permissions could find their site security compromised.
For example, it is fairly common to set incoming files to not be
readable to the anonymous user; this prevents files from being
traded through an anonymous site without the permission of the
owner. With this bug, all uploaded files are owned by the
anonymous user, with default permissions set by CMASK.
Credit goes to Michael Brennen.
SOLUTION
The patch below is Michael's version of a fix (another one!).
--- 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;
}
}
}