COMMAND
Flftpd
SYSTEMS AFFECTED
Glftpd 1.18 till 1.21b8
PROBLEM
Raymond Dijkxhoorn found following. Glftpd 1.18 till 1.21b8
(current beta) have a serious problem with the privpath
directives....
When you know the private dir names on a site, or groupdirs you
can just 'try' to get in .. and its very easy. If you know the
name of groupdir you can simply change into it using the
completion function on glftpd. If you have a private dir/group
dir, for example....
/Groups/Mygroup and you have a dir named 'test' there.
you can simply jump to it by typing 'chdir /Groups/Mygroup/t
glftpd does not check if you have the proper rights to see the
dir, it just hops in there without any problem. So if you try
a-9 on the dirnames you can see all stuff inside a private dir,,
takes some time, but with a nice script its not that hard...
SOLUTION
There's new glFtpD and its version is 1.21 and you can find them
at glftpd.deepwell.com. Currently only the FBSD4 and Linux
versions are posted. Solaris SPARC versions have been packaged
and are being posted soon.
There's workaround. Put in the attached fix, instructions are also
inside the .c file. It will ONLY exploiting of the bug on glftpd
1.20 and above, so if you're running << 1.20 then upgrade to the
latest version. In the glftpd.conf:
cscript cwd pre /bin/leakfix
leakfix.c:
/*
*** Very quick & dirty fix for the glFTPd privpath-matching leak.
*** NOTE: This fix has NOT been tested thoroughly and thus may even increase
*** your site's security problems. Use at your own risc! Update glFTPd
*** as soon as an official bugfix is out!
*** This will only work with glFTPd 1.20 and higher, because it uses the
*** CScript hook which was introduced with v1.20 ...
*** How does it work? It checks which directory a user wants to CWD into,
*** and if it's a private directory with less than e.g. 3 characters after
*** the last slash, then it denies the CWD attempt. This means a user would
*** need to know at least 3 characters of a release name stored in a private
*** directory.
*** Make sure to keep the number of characters needed to guess as low
*** as possible. For example, if you have a /private/XYZ and set the
*** number to 5, any attempt to cwd into /private/XYZ would be denied.
*** People would then have to cwd into /private first and from there into
*** XYZ. This means this bugfix would not prevent out the right people
*** from accessing their private directories, however they would be forced
*** to change into there step by step and not with an absolute pathname.
*** This as usual could lead to confusions for some intellectually
*** challanged users :)
*** You can increase the number of characters a user must guess correctly
*** below in the source, as well as the names of your private directories
*** must be specified properly here. The default matches all directories
*** containing /private, /pre or /group ... case insensitive, which means
*** /site/incoming/Groups/BLUB-PRE would also be matched correctly by
*** default.
*** To install this fix, compile it with
gcc -o leakfix leakfix.c
*** and copy the leakfix binary into your /glftpd/bin directory. Then add
cscript cwd pre /bin/leakfix
*** to your /etc/glftpd.conf file .
*** Remember this will only work with glFTPd 1.20 and higher and make sure
*** to update as soon as there is an official bugfix is out (you can remove
*** this cscript line from your glftpd.conf again then).
*** IF YOU FIND ANY ERRORS IN THIS PLEASE LET ME KNOW, FIX IT AND SHARE IT
*** WITH OTHERS.
// Hoopy <hoopy@risciso.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#define EXIT_OK 0
#define EXIT_ERROR 1
int main (int argc, char *argv[])
{
char cwdcmd[500];
int cnt;
if (argc < 3)
{
fprintf (stdout, "Read the dox on how to set this up...\n"); fflush (stdout);
return EXIT_ERROR;
}
snprintf (cwdcmd, 500, argv[1]);
for (cnt=0; cnt < strlen(cwdcmd); cnt++) cwdcmd[cnt] = tolower(cwdcmd[cnt]);
// COPY THE FOLLOWING LINE FOR EACH OF YOUR PRIVATE PATHS
if (strstr(cwdcmd, "/private") == NULL)
if (strstr(cwdcmd, "/pre") == NULL)
if (strstr(cwdcmd, "/group") == NULL)
return EXIT_OK;
if (strlen(strrchr(cwdcmd, '/')) < 4)
{
fprintf (stdout, "550CWD attempt denied, change into private directory first.\n"); fflush(stdout);
return EXIT_ERROR;
}
return EXIT_OK;
}