DRDoS

利用反弹技术进行DDoS攻击的分析 攻击力度远大于分布式DDOS攻击

DRDOS是英文“Distributed Reflection Denial of Servie Attack”的缩写,中文意思是“分布式反射拒绝服务攻击”。与DoS、DdoS不同,该方式靠的是发送带有被害者IP地址的数据包给攻击主机(有点像送错信)。由于是利用TCP/IP服务的“三握手”的第二步,因此攻击者无需给被攻击者安装木马,发动DRDoS也只要花费攻击者很少的资源。

DRDoS是通过发送带有受害者IP地址的SYN连接请求包给攻击主机DGP,然后在根据TCP三次握手的规则,这些攻击主机BGP会向源IP(受害者IP)发出SYN+ACK包来响应这些请求,造成受害者主机忙于处理这些回应而被拒绝服务攻击。

给大家举个例子,比如我以A的名义给百度写了一封信,百度的每一个工作人员都知道了这封信,而且回了信。但信的地址是A的地址,所以百度就把信回给A,A无缘无故就受到了很多信件,郁闷死了吧。这就是DRDoS与DDoS的不同之处。

介绍了分布式拒绝服务(DDoS)和反弹式拒绝服务(DRDoS)的原理,对DRDoS的原理进行了重点分析。并提出了一些检测和防范的方法。

攻击者可以通过反弹技术使我们对DDOS攻击更难以防御——利用反弹服务器反弹DDOS的洪水包,也就是说,通过发送大量的欺骗请求数据包(来源地址为victim,受害服务器,或目标服务器)给Internet上大量的服务器群,而这些服务器群收到请求后将发送大量的应答包给victim。结果是原来用于攻击的洪水数据流被大量的服务器所稀释,并最终在受害者处汇集为洪水,使受害者更难以隔离攻击洪水流,并且更难以用Traceback 跟踪技术去找到洪水流的来源。

在分布式DOS攻击(DDOS)中,攻击者事先入侵了大量服务器,并在这些服务器上植入了DDOS攻击程序,然后结合这些被入侵的服务器的网络传输力量发动攻击。利用大量的服务器发动攻击不仅增加了攻击的力度,而且更难于防范。

图 1: DDOS 攻击的结构

图一显示了以往DDOS攻击的结构:一个主机,主服务器(Master),作用是发送控制消息给事先入侵并已植入DDOS程序的从服务器群(Slave),控制从服务器群发起对目标服务器的攻击。从服务器群将产生高容量的源地址为伪造的或随机的网络数据流,并把这些数据流发送给目标服务器。因为数据流的源地址是伪造的,增加了追查的难度。

利用成百上千的从服务器不仅可以另追查的难度加大(因为难以识别大量不同的来源,需要查询大量的路由器),而且极大的阻碍了当成功追查后所需采取的行动(因为这要与大量的网络管理员联系,安装大量的网络过滤器)。

图 2: 利用反弹进行DDOS 攻击的结构

而今考虑周密的攻击者可以通过利用反弹服务器(Reflector),更好的组织他们的攻击。反弹服务器是指,当收到一个请求数据报后就会产生一个回应数据报的主机。例如,所有的WEB服务器,DNS服务器,及路由器都是反弹服务器,因为他们会对SYN报文或其他TCP报文回应SYN ACKs或RST报文,以及对一些IP报文回应ICMP数据报超时或目的地不可达消息的数据报。而攻击者可以利用这些回应的数据报对目标服务器发动DDOS攻击。

攻击者首先锁定大量的可以做为反弹服务器的服务器群,比如说100万台(这并不是件很难的工作,因为在Internet上光是WEB服务器就不止这么多的,更何况还有更多其他的机器可以作为反弹服务器)。然后攻击者们集中事先搞定的从服务器群,向已锁定的反弹服务器群发送大量的欺骗请求数据包(来源地址为victim,受害服务器或目标服务器)。反弹服务器将向受害服务器发送回应数据报。结果是:到达受害服务器的洪水数据报不是几百个,几千个的来源,而是上百万个来源,来源如此分散的洪水流量将堵塞任何其他的企图对受害服务器的连接。

图二显示了利用反弹进行DDOS攻击的结构。注意到,受害服务器不需要追查攻击的来源,因为所有攻击数据报的源IP都是真实的,都是反弹服务器群的IP。而另一方面,反弹服务器的管理人员则难以追查到从服务器的位置,因为他所收到的数据报都是伪造的(源IP为受害服务器的IP)。

原则上,我们可以在反弹服务器上利用追踪技术来发现从服务器的的位置。但是,反弹服务器上发送数据报的流量远小于从服务器发送的流量。每一个从服务器可以把它发送的网络流量分散到所有或者一大部分反弹服务器。例如:如果这里有Nr 个反弹服务器,Ns 个从服务器,每个从服务器发送的网络流量为F,那么每一个反弹服务器将产生的网络流量为:

而Nr 远大于Ns 。所以,服务器根据网络流量来自动检测是否是DDOS攻击源的这种机制将不起作用。

值得注意的是,不象以往DDOS攻击,利用反弹技术,攻击者不需要把服务器做为网络流量的放大器(发送比攻击者发送的更大容量的网络数据)。他们甚至可以使洪水流量变弱,最终才在目标服务器回合为大容量的洪水。这样的机制让攻击者可以利用不同网络结构机制的服务器作为反弹服务器,使其更容易找到足够数量的反弹服务器,用以发起攻击。

我们的分析显示,有三种特别具威胁性的反弹服务器是:DNS服务器、Gnutella服务器、和基于TCP-IP的服务器(特别是WEB 服务器),基于TCP的实现将遭受可预测初始序列号的威胁。

比较smurf与DrDoS攻击文章作者:SystEm32

近日在www.itaq.org的论坛闲逛,发现对smurf/D.R.D.O.S的讨论热闹了起来,本来我对此并无太大兴趣,但是在看了网上一些资料后,觉得有些东西似乎没讲清楚,因此特撰此文,谈谈我对smurf与D.R.D.O.S的看法.

一.SMURF攻击的概念及效果

1.概念:

Smurf攻击的命名,是从smurf这个攻击工具来的。Smurf是一种在局域网中的攻击手段,它的作用原理是基于广播地址与回应请求的,我们都知道,在局域网中,计算机被分配的ip地址的最后一位,是在1-254之间,那么最后那个255是留下来干什么的呢?其实带有这个255的地址,比如:192.168.0.255,就是这个子网的广播地址你可以这样试试看:运行->CMD.exe,输入ping 192.168.0.255(假设你的ip是192.168.0.xxx),你会看到计算机会去ping所有属于这个局域网的ip,你发出了一个echo request,却收到了253个reply响应报文。换句话说,你消耗了一份的资源去发送报文,却要消耗253倍的资源去处理接受到的报文,对比是不是很大呢?:)

从攻击者的角度来看,如何利用局域网的这个特性呢?考虑到广播地址有如此惊人的放大能力(200多倍),攻击者只要对广播地址发送大量的ICMP报文(通常是echo,也就是ping出来的东东),其引发的报文震荡是十份剧烈的,很快整个局域网中就会充斥着大量的echo与reply。但是,这样做,吃亏的是可怜的攻击者,因为所有的reply报文都是冲着发送echo报文的ip去的,如果直接这样干的话,攻击者就成了受害者...没人会这么傻,所以smurf诞生了..攻击者用互联网控制信息协议(ICMP)的应答数据包--一种特殊的ping数据包来填充受害者的路由器,这些数据包的目的IP地址同时是受害者的广播地址,而且通过伪造报文的源IP地址,所有的应答报文都将返回到受害者身上,巨大的流量将使受害者失去反应能力,甚至死机,这就是Smurf攻击。

2.效果:

看了以上这些,是不是觉得有点毛骨悚然?其实不必担心,因为Smurf看上去似乎能放大攻击力度很多很多倍,但事实如何?其实,由于现在路由器/网关的设置,带有广播地址的报文不能穿越网关,广播报文到达不了目标所在的远程局域网的,所以现在这种攻击是无效的,这也是很多人对smurf不了解的原因。

3.小结:

smurf能放大攻击,但只对本地局域网有效,不需要肉鸡,由于网关的过滤,此攻击现在已失效。

二.D.R.D.O.S攻击的概念及效果

1.概念:

D.R.D.O.S是Distributed Reflection Denial of Service Attack的缩写,直译为分布式(Distributed)反射(Reflection)拒绝服务(Denial of Service)攻击,2002年1月11日凌晨两点,grc.com遭到攻击,大量的ack应答淹没了可怜的grc.com,所幸当时grc.com的网络管理员正好在服务器上,他截取了一小部分攻击数据包,令人吃惊的是,所有攻击他的数据竟然来自于200 多个网络核心基础设施路由器,而这些路由器不可能全部存在安全漏洞。经过这件事,D.R.D.O.S开始被人们所了解,下面,我就来介绍一下D.R.D.O.S的攻击原理和编程实现。

在D.R.D.O.S的名称里有Reflection这个单词,而这,就是这个攻击方式的核心原理所在,从“反射”的字面意思来想一想,grc.com所受到的攻击来自于那么多并未被黑客入侵的核心路由器这种奇怪的现象也就不难解释了,grc.com遭到了“反射”。好比SystEm32小孩躲在Sheepxxy后面拿鸡蛋丢Jambray,J以为是Sheepxxy丢的,所以拿了一块石头(汗...)砸Sheepxxy(倒霉的Sheepxxy,残念...),发动D.R.D.O.S的攻击者冒充grc.com的IP地址向路由器们发送syn request,也就是TCP三次握手的第一步,路由器们以为grc.com要和自己建立tcp连接,所以返回ack应答,由于源ip的伪造,所有的ack应答全部都涌向了grc.com,可怜的grc.com就这样被踢下了互联网.一次成功的D.R.D.O.S就产生了。

2.效果:

在查关于D.R.D.O.S的资料时,我注意到大部分的资料都提到了分布式反射拒绝服务攻击的一个显著优点:“不需要傀儡机”,也就是不要很多肉鸡便可产生惊人的破坏。但是对于这一点,我只能非常遗憾的说:这是错的,D.R.D.O.S与传统的D.D.O.S(分布式拒绝服务攻击)相比,并没有什么实质的不同,他并不能像有些人说的那样放大攻击,也同样需要很多肉鸡才能实现,攻击的效果也和普通的syn flood(DDOS方式)差不多,并不存在效果的优越性。D.R.D.O.S发送一个syn请求给服务器,服务器便反射一个ack应答给受害者,D.R.D.O.S要想同时有1000个ack应答涌向受害者,它本身就得发送1000个syn请求给1000个服务器,从效果上来说,这和直接发送1000个syn给受害者并无不同。

3.小结:

D.R.D.O.S一向被传得很神奇,因为它"能放大攻击力度",“不需要傀儡机”,但是,事实上D.R.D.O.S不能放大攻击,并且同样要很多肉鸡,那么,D.R.D.O.S有什么优点吗?答案是肯定的,它的优点在于一些对攻击的特征检测和防御将会失效,比如对是否无效ip的判断,是否有固定的TTL值等...还有在路由器上过滤报文也很难,因为攻击你的都是正常的主机.

三.R.D.O.S的编程实现

从本质上说D.R.D.O.S和syn flood区别不大,从编程的角度来看也的却如此,我们常用的SYN ATTACK TOOLS稍做修改就可以变为R.D.O.S工具(为什么不是D.R.D.O.S?我们是学习的,不是破坏的,要分布式的工具何用呢? :P ),下面就简单对R.D.O.S的源码做点说明,完整的代码和工具可以在本期光盘中找到。

1.定义ip头部,tcp头部和tcp伪头部

typedef struct _IP_HEADER //定义IP首部
{
unsigned char h_verlen; //4位首部长度,4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;

typedef struct _PSD_HEADER //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSD_HEADER;

typedef struct _TCP_HEADER //定义TCP首部
{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq; //32位序列号
unsigned int th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;

我们使用TCP协议通信的时候,系统自动为我们填充好了这些头部,现在为了能够实现伪造源ip,我们必须自己来填充它们,在真正发出的包的结构中,是没有PSD_HEADER(TCP伪首部)的,定义PSD_HEADER仅仅是为了计算出正确的效验和,我们使用CHECKSUM子程序来计算效验和

//CheckSum:计算校验和的子函数
USHORT checksum(USHORT *buffer, int size) 
{ 
unsigned long cksum=0;
while(size >1) {
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size ) {
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}

checksum函数的算法是固定的,这里我们使用的是TCP,但它对UDP,ICMP同样适用

建立一个原始套接字

SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);

设置IP_HDRINCL,告诉系统由我们自己来填充IP首部

ErrorCode=setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int));

填充发送缓冲区,利用checksum()函数计算出tcp效验和

memcpy(SendBuf,&psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

这里要注意,很多人认为发出的包里面包含了psd_header,其实呢...

memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);

这几句就是完整的填充好了发送缓冲区,我们可以看到里面并没有psd_header : ] ,再一次证明了psd_header仅仅是为了正确地计算校验和而存在的

最后就是通过一个循环把包发出去了,代码本身很简单,注释得也很详细了,就不多讲了 : P