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;

    }