在《Web安全攻防总结(上)》一文中,我们知道常见的攻击方式XSS、CSRF、SQL注入以及命令行攻击,了解了如何防范这类攻击。本文将继续给大家介绍更凶猛的攻击DDoS、流量劫持以及利用服务器漏洞进行攻击和防御手段。
DDoS 攻击
DDoS 又叫分布式拒绝服务,全称 Distributed Denial of Service,其原理就是利用大量的请求造成资源过载,导致服务不可用,这个攻击应该不能算是安全问题,这应该算是一个另类的存在,因为这种攻击根本就是耍流氓的存在,「伤敌一千,自损八百」的行为。出于保护 Web App 不受攻击的攻防角度,还是介绍一下 DDoS 攻击吧,毕竟也是挺常见的。
DDoS 攻击可以理解为:「你开了一家店,隔壁家点看不惯,就雇了一大堆黑社会人员进你店里干坐着,也不消费,其他客人也进不来,导致你营业惨淡」。为啥说 DDoS 是个「伤敌一千,自损八百」的行为呢?毕竟隔壁店还是花了不少钱雇黑社会但是啥也没得到不是?DDoS 攻击的目的基本上就以下几个:
- 深仇大恨,就是要干死你
- 敲诈你,不给钱就干你
- 忽悠你,不买我防火墙服务就会有“人”继续干你
- 也许你的站点遭受过 DDoS 攻击,具体什么原因怎么解读见仁见智。DDos 攻击从层次上可分为网络层攻击与应用层攻击,从攻击手法上可分为快型流量攻击与慢型流量攻击,但其原理都是造成资源过载,导致服务不可用。
网络层 DDoS 防御
网络层 DDos 攻击包括 SYN Flood、ACK Flood、UDP Flood、ICMP Flood 等。
网络层的 DDoS 攻击究其本质其实是无法防御的,我们能做得就是不断优化服务本身部署的网络架构,以及提升网络带宽。当然,还是做好以下几件事也是有助于缓解网络层 DDoS 攻击的冲击:
- 网络架构上做好优化,采用负载均衡分流。
- 确保服务器的系统文件是最新的版本,并及时更新系统补丁。
- 添加抗 DDos 设备,进行流量清洗。
- 限制同时打开的 SYN 半连接数目,缩短 SYN 半连接的 Timeout 时间。
- 限制单 IP 请求频率。
- 防火墙等防护设置禁止 ICMP 包等。
- 严格限制对外开放的服务器的向外访问。
- 运行端口映射程序或端口扫描程序,要认真检查特权端口和非特权端口。
- 关闭不必要的服务。
- 认真检查网络设备和主机/服务器系统的日志。只要日志出现漏洞或是时间变更,那这台机器就可能遭到了攻击。
- 限制在防火墙外与网络文件共享。这样会给黑客截取系统文件的机会,主机的信息暴露给黑客,无疑是给了对方入侵的机会。加钱堆机器。。
- 报警。。
应用层 DDoS防御
应用层 DDoS 攻击不是发生在网络层,是发生在 TCP 建立握手成功之后,应用程序处理请求的时候,现在很多常见的 DDoS 攻击都是应用层攻击。应用层攻击千变万化,目的就是在网络应用曾耗尽你的带宽。应用层 DDoS常见的类型有:CC 攻击、DNS Flood和HTTP 慢速连接攻击。
CC 攻击最常见了,就是针对消耗资源比较大的页面不断发起不正常的请求,导致资源耗尽。因此在发送 CC 攻击前,我们需要寻找加载比较慢,消耗资源比较多的网页,比如需要查询数据库的页面、读写硬盘文件的等。通过 CC 攻击,使用爬虫对某些加载需要消耗大量资源的页面发起 HTTP 请求。
应用层的防御有时比网络层的更难,因为导致应用层被 DDoS 攻击的因素非常多,有时往往是因为程序员的失误,导致某个页面加载需要消耗大量资源,有时是因为中间件配置不当等等。而应用层 DDoS 防御的核心就是区分人与机器(爬虫),因为大量的请求不可能是人为的,肯定是机器构造的。因此如果能有效的区分人与爬虫行为,则可以很好地防御此攻击。
防御手段主要有:
- 判断 User-Agent 字段(不可靠,因为可以随意构造)
- 针对 IP + cookie,限制访问频率(由于 cookie 可以更改,IP 可以使用代理,或者肉鸡,也不可靠)
- 关闭服务器最大连接数等,合理配置中间件,缓解 DDoS 攻击。
- 请求中添加验证码,比如请求中有数据库操作的时候。
- 编写代码时,尽量实现优化,并合理使用缓存技术,减少数据库的读取操作。
- 加钱堆机器。。
- 报警。。
其他 DDoS 攻击
发起 DDoS 也是需要大量的带宽资源的,但是互联网就像森林,林子大了什么鸟都有,DDoS 攻击者也能找到其他的方式发起廉价并且极具杀伤力的 DDoS 攻击。攻击者可以利用 XSS和P2P 网络攻击。
DDoS 不可能防的住,就好比你的店只能容纳 50 人,黑社会有 100 人,你就换一家大店,能容纳 500 人,然后黑社会又找来了 1000 人,这种堆人头的做法就是 DDoS 本质上的攻防之道,「道高一尺,魔高一丈,魔高一尺,道高一丈」,讲真,必要的时候就答应勒索你的人的条件吧,实在不行就报警吧。
流量劫持
流量劫持应该算是黑产行业的一大经济支柱了吧?简直是让人恶心到吐,不吐槽了,还是继续谈干货吧,流量劫持基本分两种:DNS 劫持 和 HTTP 劫持,目的都是一样的,就是当用户访问 zhishitu.net 的时候,给你展示的并不是或者不完全是 zhishitu.net 提供的 “内容”。
DNS 劫持
DNS 劫持,也叫做域名劫持,可以这么理解,「你打了一辆车想去商场吃饭,结果你打的车是小作坊派来的,直接给你拉到小作坊去了」,DNS 的作用是把网络地址域名对应到真实的计算机能够识别的 IP 地址,以便计算机能够进一步通信,传递网址和内容等。如果当用户通过某一个域名访问一个站点的时候,被篡改的 DNS 服务器返回的是一个恶意的钓鱼站点的 IP,用户就被劫持到了恶意钓鱼站点,然后继而会被钓鱼输入各种账号密码信息,泄漏隐私。
这类劫持,要不就是网络运营商搞的鬼,一般小的网络运营商与黑产勾结会劫持 DNS,要不就是电脑中毒,被恶意篡改了路由器的 DNS 配置,基本上做为开发者或站长却是很难察觉的,除非有用户反馈,现在升级版的 DNS 劫持还可以对特定用户、特定区域等使用了用户画像进行筛选用户劫持的办法,另外这类广告显示更加随机更小,一般站长除非用户投诉否则很难觉察到,就算觉察到了取证举报更难。无论如何,如果接到有 DNS 劫持的反馈,一定要做好以下几件事:
- 取证很重要,时间、地点、IP、拨号账户、截屏、URL 地址等一定要有。
- 可以跟劫持区域的电信运营商进行投诉反馈。
- 如果投诉反馈无效,直接去工信部投诉,一般来说会加白你的域名。
HTTP 劫持
HTTP 劫持您可以这么理解,「你打了一辆车想去商场吃饭,结果司机跟你一路给你递小作坊的广告」,HTTP 劫持主要是当用户访问某个站点的时候会经过运营商网络,而不法运营商和黑产勾结能够截获 HTTP 请求返回内容,并且能够篡改内容,然后再返回给用户,从而实现劫持页面,轻则插入小广告,重则直接篡改成钓鱼网站页面骗用户隐私。能够实施流量劫持的根本原因,是 HTTP 协议没有办法对通信对方的身份进行校验以及对数据完整性进行校验。如果能解决这个问题,则流量劫持将无法轻易发生。所以防止 HTTP 劫持的方法只有将内容加密,让劫持者无法破解篡改,这样就可以防止 HTTP 劫持了。
HTTPS 协议就是一种基于 SSL 协议的安全加密网络应用层协议,可以很好的防止 HTTP 劫持。这里有篇 文章 讲的不错。HTTPS 在这就不深讲了,后面有机会我会单独好好讲讲 HTTPS。如果不想站点被 HTTP 劫持,赶紧将你的站点全站改造成 HTTPS 吧。
服务器漏洞
服务器除了以上提到的那些大名鼎鼎的漏洞和臭名昭著的攻击以外,其实还有很多其他的漏洞,往往也很容易被忽视,在这个小节也稍微介绍几种。
越权操作漏洞
如果你的系统是有登录控制的,那就要格外小心了,因为很有可能你的系统越权操作漏洞,越权操作漏洞可以简单的总结为 「A 用户能看到或者操作 B 用户的隐私内容」,如果你的系统中还有权限控制就更加需要小心了。所以每一个请求都需要做 userid 的判断。
以下是一段有漏洞的后端示意代码:
// ctx 为请求的 context 上下文
let msgId = ctx.params.msgId;
mysql.query(
'SELECT * FROM msg_table WHERE msg_id = ?',
[msgId]
);
知识兔以上代码是任何人都可以查询到任何用户的消息,只要有 msg_id 就可以,这就是比较典型的越权漏洞,需要如下这么改进一下:
// ctx 为请求的 context 上下文
let msgId = ctx.params.msgId;
let userId = ctx.session.userId; // 从会话中取出当前登陆的 userId
mysql.query(
'SELECT * FROM msg_table WHERE msg_id = ? AND user_id = ?',
[msgId, userId]
);
知识兔嗯,大概就是这个意思,如果有更严格的权限控制,那在每个请求中凡是涉及到数据库的操作都需要先进行严格的验证,并且在设计数据库表的时候需要考虑进 userId 的账号关联以及权限关联。
目录遍历漏洞
目录遍历漏洞指通过在 URL 或参数中构造 ../,./ 和类似的跨父目录字符串的 ASCII 编码、unicode 编码等,完成目录跳转,读取操作系统各个目录下的敏感文件,也可以称作「任意文件读取漏洞」。
目录遍历漏洞原理:程序没有充分过滤用户输入的 ../ 之类的目录跳转符,导致用户可以通过提交目录跳转来遍历服务器上的任意文件。使用多个.. 符号,不断向上跳转,最终停留在根 /,通过绝对路径去读取任意文件。
目录遍历漏洞几个示例和测试,一般构造 URL 然后使用浏览器直接访问,或者使用 Web 漏洞扫描工具检测,当然也可以自写程序测试。
http://somehost.com/../../../../../../../../../etc/passwd
http://somehost.com/some/path?file=../../Windows/system.ini
# 借助 %00 空字符截断是一个比较经典的攻击手法
http://somehost.com/some/path?file=../../Windows/system.ini%00.js
# 使用了 IIS 的脚本目录来移动目录并执行指令
http://somehost.com/scripts/..%5c../Windows/System32/cmd.exe?/c+dir+c:\
知识兔防御 方法就是需要对 URL 或者参数进行 ../,./ 等字符的转义过滤。
物理路径泄漏
物理路径泄露属于低风险等级缺陷,它的危害一般被描述为「攻击者可以利用此漏洞得到信息,来对系统进一步地攻击」,通常都是系统报错 500 的错误信息直接返回到页面可见导致的漏洞。得到物理路径有些时候它能给攻击者带来一些有用的信息,比如说:可以大致了解系统的文件目录结构;可以看出系统所使用的第三方软件;也说不定会得到一个合法的用户名(因为很多人把自己的用户名作为网站的目录名)。
防止这种泄漏的方法就是做好后端程序的出错处理,定制特殊的 500 报错页面。
源码暴露漏洞
和物理路径泄露类似,就是攻击者可以通过请求直接获取到你站点的后端源代码,然后就可以对系统进一步研究攻击。那么导致源代码暴露的原因是什么呢?基本上就是发生在服务器配置上了,服务器可以设置哪些路径的文件才可以被直接访问的,这里给一个 koa 服务起的例子,正常的 koa 服务器可以通过 koa-static 中间件去指定静态资源的目录,好让静态资源可以通过路径的路由访问。比如你的系统源代码目录是这样的:
|- project
|- src
|- static
|- ...
|- server.js
知识兔你想要将 static 的文件夹配成静态资源目录,你应该会在 server.js 做如下配置:
const Koa = require('koa');
const serve = require('koa-static');
const app = new Koa();
app.use(serve(__dirname + '/project/static'));
知识兔但是如果配错了静态资源的目录,可能就出大事了,比如:
// ...
app.use(serve(__dirname + '/project'));
知识兔这样所有的源代码都可以通过路由访问到了,所有的服务器都提供了静态资源机制,所以在通过服务器配置静态资源目录和路径的时候,一定要注意检验,不然很可能产生漏洞。
最后,希望 Web 开发者们能够管理好自己的代码隐私,注意代码安全问题,比如不要将产品的含有敏感信息的代码放到第三方外部站点或者暴露给外部用户,尤其是前端代码,私钥类似的保密性的东西不要直接输出在代码里或者页面中。也许还有很多值得注意的点,但是归根结底还是绷住安全那根弦,对待每一行代码都要多多推敲。
本文采自:zoumiaojiang.com,小编略作修改,感谢作者:zoumiaojiang