新人开车——应用层拒绝服务攻击
一、DDOS介绍
DDOS又称为分布式拒绝服务,全称是Distributed Denial of Service。DDOS本是利用合理的请求造成资源过载,导致服务不可用。
分布式拒绝服务攻击,将正常的请求放大了若干倍,通过若干个网络节点同时发起攻击,以达成规模效应。这些网络节点往往是黑客们所控制的“肉鸡”,数量达到一定规模后,就形成了一个僵尸网络。大量的僵尸网络,甚至达到了数万、数十万台的规模。如此规模的僵尸网络发起的DDOS攻击,几乎是不可能阻挡的。
常见的DDOS攻击有SYN flood、UDP flood、ICMP flood等。其中SYN flood 是一种最为经典的DDOS攻击,其发现在1996年,但至今仍然保持这非常强大的生命力。SYN flood 如此猖獗是因为它利用了TCP协议设计中的缺陷,而tcp/ip协议是整个互联网的基础,牵一发而动全身,如今想要修复这样的缺陷几乎成为不可能的事情。
想要理解DDOS还要知道TCP三次握手过程:
1)、客户端向服务器端发送一个syn包,包含客户端使用的端口号和初始序列号x;
2)、服务器端收到客户端发送来的syn包后,向客户端发送一个syn加ack都置位的TCP报文,包含确认号x+1和服务器端的初始序列号y;
3)、客户端收到服务器端返回的syn+ack保温后,向服务器端返回一个确认号为y+1、序号为X+1的ACK报文,一个标准的TCP连接完成。
而SYN FLOOD在攻击时,首先伪造大量的源ip地址,分别向服务器端发送大量的SYN包,此时服务器端会返回syn/ack包,因为源地址路是伪造的,所以伪造的ip并不会应答,服务器端并没有收到伪造ip的回应,会重试3-5次并且等待一个syn time,如果超时则丢弃这个连接。攻击者大量发送这种伪造源地址的syn请求,服务器端将会小号非常多的资源(cpu和内存)来处理这些半连接,同时还要不断的对这些ip进行syn/ack重试。最后的结果是服务器无暇理睬正常的请求,导致拒绝服务攻击。
对抗syn flood的主要措施有syn cookie、syn proxy、safereset算法。syn cookie的主要思想是为每一个ip地址分配一个"cookie",并统计每一个ip地址访问频率。如果在短时间内收到大量的来自同一个ip地址的数据包,则认为收到攻击,之后来自这个ip地址的包将被丢弃。
对抗DDOS的网络设备可以串联或者并联在网络出口处。当攻击流量超过了网络设备,甚至带宽的最大负荷时,网络仍将瘫痪。
二、应用层DDOS
应用层DDOS,不同于网络层,由于发生在应用层,因此TCP三次握手已经完成,连接已经建立,所以发起攻击的ip地址也都是真实的。
那么应用层DDOS到底是怎么回事呢?这就要从“cc攻击”说起了。
2.1 CC攻击
CC攻击的原理非常简单,就是对一些消耗资源较大的应用页面不断发起正常的请求,以达到消耗服务端资源的目的。
应用层DDOS攻击还可以通过以下方式完成: 在黑客入侵了一个流量很大的网站后,通过篡改页面,将巨大的用户流量分流到目标网站。
比如,在大流量网站siteA上插入一段代码:
<iframe src="http://target" height=0 width=0> </iframe>
那么所有访问该页面的siteA用户,都将对此target发起一次http get请求,这可能直接导致target拒绝服务。
应用层DDOS攻击是针对服务器性能的一种攻击,那么许多优化服务器性能的方法,都或多或少地能缓解此种攻击。比如将使用频率高的数据放在memcache(分布式的告诉缓存系统)中,相对于查询数据库所消耗的资源来说,查询memcache所消耗的资源可以忽略不计。但是很多性能优化的方案并非是为了对抗应用层DDOS攻击而设计的,因此攻击者想要找到一个资源消耗大的页面并不困难。比如当memcache查询没有命中时,服务器必然会查询数据库,从而增大服务器资源的消耗,攻击者只需要找到这样的页面即可。同时攻击者处理触发“读”数据操作外,还可以触发“写”数据操作,“写”数据操作的行为一般都会导致服务器操作数据库。
2.2 防御措施
1、最常见的针对应用层DDOS攻击的防御措施,是在应用层中针对每个“客户端”做一个请求频率的限制。思路很简单,通过IP地址与Cookie定位一个客户端,如果客户端的请求在一定时间内过于频繁,则对于之后来自该客户端的所有请求都重定位到一个出错页面。
然而这种防御方式并不完美,因为它在客户端的判断依据上并不是永远可靠的。如果IP地址和Cookie同时都发生了变化,那么久无法再定位到同一个客户端了。那么如何让IP地址发生变化呢?使用“代理服务器”是一个常见的做法。在实际的攻击中,大量使用代理服务器或傀儡机来隐藏攻击者的真实ip地址,已经成为一种成熟的攻击模式。攻击者使用这些方法可不断地变化Ip地址,就可以绕过服务器对单个ip地址请求频率的限制了
应用层DDOS攻击并非是一个无法解决的难题,一般来说,我们可以从以下几个方面着手。
(1)应用代码要做好性能优化。合理地使用memcache就是一个很好的优化方案。
(2)在网络架构上做好优化。善于利用负载均衡分流,避免用户流量集中在单台服务器上。同时可以充分利用好CDN和镜像站点的分流作用,缓解主站压力。
(3)实现一些对抗手段,比如限制每个IP地址的请求频率。
2、验证码
验证码是互联网中常用的技术之一,它的英文简称是CAPTCHA(全自动区分计算机和人类的图灵测试)。在很多时候,如果可以忽略对用户体验的影响,那么引入验证码这一手段能够有效地阻止自动化的重放行为。验证码发明的初衷是为了识别人与机器。
3、一种比较可靠的方法是让客户端解析一段Javascript,并给很出正确的运行结果。。但是这种方法并不是万能的,有的自动化脚本是内嵌在浏览器中的“内挂”,就无法检测出来了。
4、除了人机识别外,还可以在Web Server这一层做些防御,其好处是请求尚未到达后端的应用程序里,因此可以起到一个保护作用。Yahoo为我们提供了一个解决思路。因为发起应用层DDOS攻击的IP地址都是真实的,所以在实际情况中,攻击者的IP地址其实也不可能无限制增长。假设攻击者有1000个IP地址发起攻击,若果请求了10000次,则平均每个IP地址请求同一页面达到10次,攻击如果持续下去,单个IP地址的请求也将变多,但无论如何变化,都是在这1000个IP地址的范围内做轮询。为此Yahoo实现了一套算法,根据IP地址和Cookie等信息,可以计算客户端的请求频率并进行拦截。Yahoo设计的这套系统也是为WEB server 开发的一个模块,但在整体架构上会有一台master服务器集中计算所有ip地址的请求频率,并同步策略到每台web server上。
三、资源耗尽攻击
除了cc攻击外,攻击者还可能利用一些web server 的漏洞或设计缺陷,直接造成拒绝服务。下面看几个典型的例子,并由此分析此类(分布式)拒绝服务攻击的本质。
3.1 slowloris攻击
slowloris是在09年由著名的web安全专家RSnake提出的一种攻击方法,其原理是以极低的速度往服务器发送HTTP请求。由于web server 对于并发的连接数都有一定的上限,因此若是恶意地占用住这些连接不释放,那么web server的所有连接都将被恶意连接占用,从而无法接受新的请求,导致拒绝服务攻击。
要保持住这个连接,RSnake构造了一个畸形的HTTP请求,准备地说,是一个不完整的HTTP请求。如下:
GET / HTTP/1.1 \r\n
Host : host \r\n
.........
在正常的HTTP包头中,是以两个CLRF表示HTTP Headers部分结束。如:
content-length: 42 \r\n\r\n
由于web server只收到了一个\r\n,因此将认为HTTP Headers部分没有结束,并保持此连接不释放,继续等待完整的请求。此时客户端再发送任意HTTP头,保持住连接即可。当构造多个连接后,服务器的连接数很快就会达到上限。
此类拒绝服务攻击的本质,实际上是对有限资源的无限滥用。
“有限”的资源是指web server 的连接数,这是一个有上限的值,比如apache中这个值由MaxClients定义。如果恶意客户端可以无限制地将连接数占满,就完成了对有限资源的恶意消耗,导致拒绝服务。
3.2 HTTP POST DOS
其原理是在发送HTTP POST包时,指定一个非常大的Content-Length值,然后以很低的速度发包,比如10-100s发一个字节,保持住这个连接不断开。这样当客户端连接数多了以后,占用住了web server 的所有可用连接,从而导致DOS。
由此可知,这种攻击的本质也是针对Apache的MaxClients限制的。
要解决此类问题,可以使用web应用防火墙,或者一个定制的web server安全模块。
由以上两个例子我们很自然地联想到,凡是资源有“限制”的地方,都可能发生资源滥用,从而导致拒绝服务,也就是 一种“资源耗尽型攻击”
出于可用性和物理条件的限制,内存、进程数、存储空间等资源都不可能无限制地增长,因此如果未对不可信任的资源使用者进行配额的限制,就有可能造成拒绝服务。内存泄漏是程序员经常需要解决的一种BUG,而在安全领域中,内存泄漏则被认为是一种能够造成拒绝服务攻击的方式。
3.3 server limit dos
Cookie也能造成一种拒绝服务。
web server 对http包头都有长度限制,以Apache举例,默认是8192字节。也就是说apache能接受的最大HTTP包头大小为8192字节。如果客户端发送的HTTP包头超过这个大小,服务器就会返回一个4xx错误。
假设攻击者通过XSS攻击,恶意地往客户端写入一个超长的Cookie,则该客户端再清空Cookie之前,将无法再访问该Cookie所在域的任何页面。这是因为Cookie也是放在http包头里发送的,而web server 默认会认为这是一个超长的非正常请求,从而导致“客户端”的拒绝服务。
要解决此问题,需要调整Apache配置参数LimitRequestFieldSize,这个参数设置为0时,对HTTP包头的大小没有限制。
四、一个正则引发的血案:ReDOS
与前面提到的资源耗尽攻击略有不同的是,ReDos是一种代码实现上的缺陷。正则表达式是一个状态机,每个状态和输入符号都可能有许多不同的下一个状态。正则解析引擎将遍历所有可能的路径直到最后。由于每个状态都有若干个“下一个状态”,因此决策算法将逐个尝试每个“下一个状态”,因此决策算法将逐个尝试每个“下一个状态”,直到找到一个匹配的。
比如这个正则表达式:
^(a+)+$
当输入 aaaaX时,它有16种可能的路径,引擎很快能遍历完。但是当输入aaaaaaaaaaaaaaX时,就会变成几千条可能的路径,此后每增加一个“a”,路径的数量都会翻倍。
这极大地增加了正则引擎解析数据时的消耗。当用户恶意构造输入时,这些有缺陷的正则表达式就会消耗大量的系统资源(比如CPU和内存),从而导致整台服务器性能下降,表现的结果是系统速度很慢,有进程或服务失去响应,与拒绝服务的后果是一样的。
在检查应用安全时,一定不能忽略ReDos可能造成的影响。在本节中提到的几种存在缺陷的正则表达式和测试用例,可以加入安全评估的流程中。