此文源于近日公司安全部门给我们的一次分享,之前我一直以为会有类似于0day之类的东东(我自作多情了-_-!),结果分享的重头戏却是演示HTTP Slow Header 和 HTTP Slow POST 攻击。
第一次看到这个攻击方式是去年在刺的博客,当时只是大致看了一下原理。后来又在第二届中国地方与行业网站峰会上看到刺的演讲里也有类似的攻击演示,因此这算是第三次了。分享结束以后有同学希望得到演示工具,但似乎未能如愿,于是就想自己写一个,只要是hack相关的东东总能让我莫名的兴奋。
首先两种攻击的原理:
- GET请求的时候故意不发送完整的http header,等待一段时间后再把剩下的部分发完。
- POST请求的时候设置一个比较大的content-length,然后以很低的速度发包,比如10s发一个字节。
两种攻击方式目的都是一样:hold住这个连接不断开。这样当客户端连接多了后,占用住了webserver的所有可用连接。
然后就是代码实现,先用自己最熟悉的PHP实现了建立一个SOCKET连接然后发送部分数据包,sleep,继续发送,如此循环直到发完全部数据。到这里我突然遇到了一个问题,PHP是不支持多线程的,那么如何实现高并发呢?采用循环的方式无法实现并发的效果。后来@HeseyWang 同学建议我用curl_multi_exec,完善了一下代码果然可以实现并发,后来发现其实采用pcntl_fork多进程也是可以实现的。
但是心里对PHP的多线程总是不太放心,于是又开始折腾Python代码。第一步建立socket连接,构造http 请求比较顺利,第二步是多线程,Google 之查到threading.Thread可以,折腾了半天总算是实现了。但在实际测试的时候发现多线程的并发连接数最高只能在1000多一点,考虑到公司的网络带宽肯定不是问题,于是尝试同时多开程序的方法,结束一不小心把测试的机器负载压到了850,直接失去响应,SSH都连不上。汗
看来只能把程序加上多进程才能实现高并发的要求,于是又折腾起了多进程。在此之前没接触过多进程多线程相关的东东,所以过程也比较曲折,又捣鼓了一天总算把多进程功能也实现了。
代码比较简陋,我就不贴出来了,文末附张图吧。
晚上拿同学的电脑做了测试,总结出以下几点:
- HTTP Slow POST 攻击因为一开始发送的是完整的HTTP头,
所以URI是必须存在的,如果请求一个不存在的URI,Apache会直接返回404而不会等你继续发送POST数据。 - HTTP Slow Header 攻击因为一开始发送的不是完整的HTTP头,所以URI可以任意构造,Apache会一直等待你发送完最后的字符(n)才返回404,此时攻击已经完成。
- mod-evasive 只能在一定程度上缓解这两种攻击,攻击者可以通过调整建立连接数的频率来躲避mod-evasive的防御。同样减小timeout参数也只能是缓解,如果攻击者发包的sleep时间小于timeout参数就能绕过。
解决方法:
- 小网站可以通过限制单个IP的最大连接数解决,但是如果这种攻击配合僵尸网络的话就无能为力了(小网站本来也就顶不住DDOS,似乎有点多此一举)。
- 引入mod-security模块,这个应该是比较好的解决方案,有能力的话自己写一个模块也行(网上已经有人给出关键代码),牛叉的公司整个webserver都是自己写的话就更容易解决了。
- 放弃Apache,改用nginx
附图: