Discussion:
[Proftpd-devel] [Proftpd-user] ProFTPD security issue on FreeBSD
(too old to reply)
TJ Saunders
2011-12-05 19:10:26 UTC
Permalink
Does anyone have any suggested work-arounds to the issue posted at
http://lists.grok.org.uk/pipermail/full-disclosure/2011-November/084372.html
The FreeBSD stock daemon has been patched to check for this condition,
but not sure where to start with proftpd on this issue
Here's a list of workarounds (not solutions) which can help to mitigate
the issue:

1. Use the following in your proftpd.conf:

<Global>
RootRevoke on
</Global>

This causes proftpd to drop all root privileges after the client has
authenticated. The "Roaring Beast" exploit requires root privs for
attaching to a root-running process on the FreeBSD box; by using
"RootRevoke on", you prevent the exploit from attaching to that root-owned
process. (Root privs are kept in order to satisfy the RFC-mandated
requirement to use L-1 as the source port for an active data transfer,
where L is the control port. Using "RootRevoke on" will cause active data
transfers not to work, if your proftpd uses a control port below 1025.)

2. Try to prevent the necessary exploit directories from being created via
FTP, by using <Directory> and <Limit> sections, i.e.:

# For non-<Anonymous> chrooted logins, use this.
#
# NOTE: it ASSUMES that you are using "DefaultRoot ~" to chroot users to
# their respective home directories. If you use a different chroot
# directory, replace '~' with that chroot directory in the configs
# below.
<Directory ~/etc>
<Limit ALL>
DenyAll
</Limit>
</Directory>

<Directory ~/lib>
<Limit ALL>
DenyAll
</Limit>
</Directory>

# And for <Anonymous> logins where uploads are allowed, use:
<Anonymous ...>
...
<Directory etc>
<Limit ALL>
DenyAll
</Limit>
</Directory>

<Directory lib>
<Limit ALL>
DenyAll
</Limit>
</Directory>
</Anonymous>

3. I'll be working on a module which takes a configurable list of files;
the module will periodically check for the existence of these files (e.g.
with the chrooted session) and if present, delete them.

For the benefit of others with this issue, please report back to the list
if you use one (or both) of the above configurations, and how well it
appears to be working. I will keep the list apprised of progress on the
file-deleting module.

TJ

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The world is not to be put in order; the world is order,
incarnate. It is for us to harmonize with this order.

-Henry Miller

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TJ Saunders
2011-12-05 23:29:28 UTC
Permalink
Post by TJ Saunders
Here's a list of workarounds (not solutions) which can help to mitigate
<Global>
RootRevoke on
</Global>
This causes proftpd to drop all root privileges after the client has
authenticated. The "Roaring Beast" exploit requires root privs for
attaching to a root-running process on the FreeBSD box; by using
"RootRevoke on", you prevent the exploit from attaching to that root-owned
process. (Root privs are kept in order to satisfy the RFC-mandated
requirement to use L-1 as the source port for an active data transfer,
where L is the control port. Using "RootRevoke on" will cause active data
transfers not to work, if your proftpd uses a control port below 1025.)
2. Try to prevent the necessary exploit directories from being created via
# For non-<Anonymous> chrooted logins, use this.
#
# NOTE: it ASSUMES that you are using "DefaultRoot ~" to chroot users to
# their respective home directories. If you use a different chroot
# directory, replace '~' with that chroot directory in the configs
# below.
<Directory ~/etc>
<Limit ALL>
DenyAll
</Limit>
</Directory>
<Directory ~/lib>
<Limit ALL>
DenyAll
</Limit>
</Directory>
<Anonymous ...>
...
<Directory etc>
<Limit ALL>
DenyAll
</Limit>
</Directory>
<Directory lib>
<Limit ALL>
DenyAll
</Limit>
</Directory>
</Anonymous>
If you are running a newer proftpd (e.g. proftpd-1.3.4a), you can use
finer-grained control over the etc/ directory, e.g.:

<Directory etc>
<Limit WRITE>
DenyFilter nsswitch\.conf$
</Limit>
</Directory>

to prevent the uploading (or renaming) of the 'nsswitch.conf' file to that
directory, which is a necessary component of the "Roaring Beast" exploit.
Likewise, you can prevent .so files from being uploaded to the lib
directory using:

<Directory lib>
<Limit WRITE>
DenyFilter \.so$
</Limit>
</Directory>

Also, in case anyone is curious, the "Roaring Beast" exploit does not work
for proftpd's mod_sftp connections. The mod_sftp module *always* drops
root privileges automatically (i.e. it does the functional of "RootRevoke
on"), unless explicitly configured to retain root privs.

TJ

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To See a World in a Grain of Sand,
And a Heaven in a Wild Flower,
Hold Infinity in the palm of your hand,
And Eternity in an hour.

-William Blake

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mike Tancsa
2011-12-06 22:09:29 UTC
Permalink
Post by TJ Saunders
Also, in case anyone is curious, the "Roaring Beast" exploit does not work
for proftpd's mod_sftp connections. The mod_sftp module *always* drops
root privileges automatically (i.e. it does the functional of "RootRevoke
on"), unless explicitly configured to retain root privs.
Hi,
I have been trying to understand where it is in the code that triggers
the bogus lib to be loaded ? At that point, could you not drop privs to
make sure that the lib is not loaded as root ?

In FreeBSD's ftpd, it was a simple patch in popen.c

---
libexec/ftpd/popen.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/libexec/ftpd/popen.c b/libexec/ftpd/popen.c
index 8a739dc..9f80507 100644
--- a/libexec/ftpd/popen.c
+++ b/libexec/ftpd/popen.c
@@ -143,6 +143,9 @@ ftpd_popen(char *program, char *type)
}
(void)close(pdes[1]);
}
+ /* Drop privileges before proceeding */
+ if (getuid() != geteuid() && setuid(geteuid()) < 0)
+ _exit(1);
if (strcmp(gargv[0], _PATH_LS) == 0) {
/* Reset getopt for ls_main() */
optreset = optind = optopt = 1;
--
1.7.7.2
--
-------------------
Mike Tancsa, tel +1 519 651 3400
Sentex Communications, ***@sentex.net
Providing Internet services since 1994 www.sentex.net
Cambridge, Ontario Canada http://www.tancsa.com/
TJ Saunders
2011-12-06 22:14:59 UTC
Permalink
Post by Mike Tancsa
I have been trying to understand where it is in the code that triggers
the bogus lib to be loaded ? At that point, could you not drop privs to
make sure that the lib is not loaded as root ?
As far as I can tell, the bogus libraries are loaded by FreeBSD's libc,
whenever an application (like proftpd) makes libc calls such as
getpwuid(3), getpwnam(3), getgrgid(3), etc -- which are all used to look
up the names of users/groups associated with the UIDs/GIDs for a file.
This information is used to format the directory listing data. Systems
which use NSS modules for resolving/lookups of IDs to names use
/etc/nsswitch.conf, and several .so libraries, for doing the lookups below
the libc layer (and thus completely outside of the scope of userland
applications like proftpd).
Post by Mike Tancsa
In FreeBSD's ftpd, it was a simple patch in popen.c
That works for FreeBSD's ftpd because it uses fork+exec of the /bin/ls
process to obtain e.g. directory listings -- they drop the root privs
after the popen(3) call, *for that /bin/ls process* (but not necessarily
for the session process).

ProFTPD does NOT use popen(3) or fork+exec; the mod_ls module has an
internal implementation for obtaining the directory listing information.

This is why the best solution to date is to add:

<Global>
RootRevoke on
</Global>

to the proftpd.conf. It tells proftpd to drop root privs for the entire
session, regardless of what the client is doing, right
after authentication.

TJ

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

No man can justly censure or condemn another,
because indeed no man truly knows another.

-Sir Thomas Browne

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Loading...