在互联网时代,数据安全与个人隐私受到了前所未有的挑战,各种新奇的攻击技术层出不穷。如何才能更好地保护我们的数据?通过本次学习《Web 安全攻防实战》主要总结 6 大攻击和防御手段,它们分别是:XSS、CSRF、SQL 注入、命令行注入、DDoS 攻击、流量劫持。
一、XSS
XSS (Cross-Site Scripting),跨站脚本攻击,因为缩写和 CSS 重叠,所以只能叫 XSS。跨站脚本攻击是指通过存在安全漏洞的 Web 网站注册用户的浏览器内运行非法的 HTML 标签或 JavaScript 进行的一种攻击。浏览器将用户输入的内容,当做脚本执行,执行了恶意的功能,这种针对用户浏览器的攻击即跨站脚本攻击。这种攻击可以达到攻击者盗取 Cookie、盗取账户、恶意软件下载、键盘记录、广告引流等多种恶意目的。XSS 的攻击方式千变万化,但还是可以大致细分为几种类型:反射型、存储型、DOM 型。
1. 反射型 XSS
反射型 XSS 也叫非持久型 XSS,一般是通过给别人发送带有恶意脚本代码参数的 URL,当 URL 地址被打开时,特有的恶意代码参数被 HTML 解析、执行。
应用程序或 API 包括未经验证和未经转义的用户输入,直接作为 HTML 输出的一部分。一个成功的攻击可以让攻击者在受害者的浏览器中执行任意 的 HTML 和 JavaScript 。
XSS 攻击步骤如下图所示:
反射型 XSS 漏洞攻击有以下几点特征:
即时性,不经过服务器存储,直接通过 HTTP 的 GET 和 POST 请求就能完成一次攻击,直接拿到用户隐私数据。
非持久化,必须用户点击带有特定参数的链接才能引起,攻击者需要诱骗点击。
反馈率低,所以较难发现和响应修复。
盗取用户敏感保密信息。
反射型 XSS 的限制与防御:
危害范围相对较小。
多为一次点击触发一次。
对陌生的链接,不要随意点开。
反射型 XSS 的危险程度相对比较小,仅执行脚本的用户,只要用户抵制住外部的诱惑便可以防止这类攻击。下面介绍危害更大的存储型 XSS 漏洞。
2. 存储型 XSS
存储型 XSS 漏洞,也被称为持久型 XSS 漏洞,存储型 XSS 是指应用程序通过 Web 请求获取不可信赖的数据,在未检验 数据是否存在 XSS 代码的情况下,便将其存入数据库。当下一次从数据库 中获取该数据时程序也未对其进行过滤,页面再次执行 XSS 代码,存储型 XSS 可以持续攻击用户。
存储型 XSS 出现位置:留言板、评论区、用户头像、个性签名、博客。
存储型 XSS 主要注入页面方式和反射型 XSS 漏洞类似,只不过存储型的不是来源于 URL,refferer,forms 等,而是来源于后端从数据库中读出来的数据。存储型 XSS 攻击不需要诱骗点击,攻击者只需要在提交表单的地方完成注入即可,但是这种 XSS 攻击的成本相对还是很高。攻击成功需要同时满足以下几个条件:
POST 请求提交表单后端没做转义直接入库。
后端从数据库中取出数据没做转义直接输出给前端。
前端拿到后端数据没做转义直接渲染成 DOM。
存储型 XSS 有以下几个特点:
持久性,植入在数据库中。
危害面广,甚至可以让用户机器变成 DDoS 攻击的肉鸡。
盗取用户敏感私密信息。
针对存储型 XSS 的防御:
对用户的输入进行合理验证,对特殊字符(如<、>、’、”等)以及 <script>、 javascript 等进行过滤。
script过滤 | 大小写,双写绕过 |
输入长度过滤 | 在js中,抓包修改 |
/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i | <img src=x onerror=alert("xss")> |
()过滤 | <script>alert`xss`</script> |
' " 过滤 | <script>alert(/xss/)</script> |
采用 OWASP ESAPI 对数据输出 HTML 上下文中不同位置(HTML 标签、HTML 属性、JavaScript 脚本、CSS、URL)进行恰当的输出编码。
设置 HttpOnly 属性,避免攻击者利用跨站脚本漏洞进行 Cookie 劫持攻击。在 Java EE 中,给 Cookie 添加 HttpOnly 的代码如下:
复制
cookie.setHttpOnly(true);
tools.sessions.httponly = True
session.cookie_httponly =1
复制
3. DOM 型 XSS
DOM 型 XSS 其实是一种特殊类型的反射型 XSS,通过 JS 操作 DOM 树动态地输出数据到页面,而不依赖于将数据提交给服务器端,它是基于 DOM 文档对象模型的一种漏洞。
与反射型的异同点和危害:
同:都是没有控制好输入,并且把 javaScript 脚本 输入作为输出插入到 HTML 页面。
异:反射型 XSS 是经过后端语言后,页面引用后端输出生效。DOM XSS 是经过 JS 对 DOM 树直接操作后插入到页面。
危害性:前后端分离,不经过 WAF 的检测。
示例:
针对 DOM 型 XSS 的防御:
检测的流程就是通过查看代码是否有 document.write、eval、window 之类能造成危害的地方,然后通过回溯变量和函数的调用过程,查看用户是否能控制输入。如果能控制输入,就看看是否能复现,能复现就说明存在 DOM XSS,需要对输入的数据进行编码。
当业务需要必须得将用户输入的数据放入 html,那就要尽量使用安全的方法,比如 innerText(),testContent() 等。在使用框架时尽量使用框架自带的安全函数。
二、CSRF
1. HTTP
HTTP协议是 (Hyper Text Transfer Protocol) 超文本传输协议的缩写,主要用于Web端的内容获取,也就是访问 Web 页面所使用的协议。
HTTP 是一种无状态协议,即服务器不会保留与客户交易时的状态,用户A 在很短的时间间隔内向 Web 服务器发送了两次同样的请求,服务器并不会因为已经响应了该请求一次就不对第二次请求进行响应,因为服务器并不知道已经响应过一次该请求假设用户在网站A的某一个页面上已经完成了登录操作,当在该网站的另一个页面上执行的操作需要验证用户登录的时候任然需要用户再次登录,因为 HTTP 并不知道你已经登录,它不会维持你的登录状态。
2. cookie
为了让服务器能够记住用户引入了 cookie 机制。
3. 示例
用户登录的数据包
响应的数据包
修改请求数据包的Cookie为管理员的 cookie
这样一来,攻击者就可以在不输入密码的情况下直接登录后台了。数据包的中 cookie 的值是浏览器从本地存储中取出,并自动填充到数据包中,如果攻击者控制登录目标网站了后台的浏览器发送数据包到目标网站修改目标网站的数据。浏览器会自动完成 cookie 的填充,目标网站会误认为该数据包就是管理员发送的,会以管理员的权限进行相关的操作。
1. CSRF 原理
下图大概描述了 CSRF 攻击的原理,可以理解为有一个小偷在你配钥匙的地方得到了你家的钥匙,然后拿着要是去你家想偷什么偷什么。
完成 CSRF 攻击必须要有三个条件:
用户已经登录了站点 A,并在本地记录了 cookie。
在用户没有登出站点 A 的情况下(也就是 cookie 生效的情况下),访问了恶意攻击者提供的引诱危险站点 B (B 站点要求访问站点A)。
站点 A 没有做任何 CSRF 防御。
你也许会问:「如果我不满足以上三个条件中的任意一个,就不会受到 CSRF 的攻击」。其实可以这么说的,因为你不能保证以下情况不会发生:
你不能保证你登录了一个网站后,不再打开一个 tab 页面并访问另外的网站,特别现在浏览器都是支持多 tab 的。
你不能保证你关闭浏览器了后,你本地的 cookie 立刻过期,你上次的会话已经结束。
上图中所谓的攻击网站 B,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
2. 预防 CSRF
CSRF 的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的 CSRF 防御也都在服务端进行。服务端的预防 CSRF 攻击的方式方法有多种,但思路上都是差不多的,主要从以下两个方面入手:
正确使用 GET,POST 请求和 cookie。
在非 GET 请求中增加 token。
一般而言,普通的 Web 应用都是以 GET、POST 请求为主,还有一种请求是 cookie 方式。我们一般都是按照如下规则设计应用的请求:
GET 请求常用在查看,列举,展示等不需要改变资源属性的时候(数据库 query 查询的时候)
POST 请求常用在 From 表单提交,改变一个资源的属性或者做其他一些事情的时候(数据库有 insert、update、delete 的时候)
当正确的使用了 GET 和 POST 请求之后,剩下的就是在非 GET 方式的请求中增加随机数,这个大概有三种方式来进行:
为每个用户生成一个唯一的 cookie token,所有表单都包含同一个伪随机值,这种方案最简单,因为攻击者不能获得第三方的 cookie(理论上),所以表单中的数据也就构造失败,但是由于用户的 cookie 很容易由于网站的 XSS 漏洞而被盗取,所以这个方案必须要在没有 XSS 的情况下才安全。
每个 POST 请求使用验证码,这个方案算是比较完美的,但是需要用户多次输入验证码,用户体验比较差,所以不适合在业务中大量运用。
渲染表单的时候,为每一个表单包含一个 csrfToken,提交表单的时候,带上 csrfToken,然后在后端做 csrfToken 验证。
CSRF 的防御可以根据应用场景的不同自行选择。CSRF 的防御工作确实会在正常业务逻辑的基础上带来很多额外的开发量,但是这种工作量是值得的,毕竟用户隐私以及财产安全是产品最基础的根本。
三、SQL 注入
SQL 注入漏洞(SQL Injection)是 Web 开发中最常见的一种安全漏洞。可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出文件等一系列恶意操作,甚至有可能获取数据库乃至系统用户最高权限。
而造成 SQL 注入的原因是因为程序没有有效的转义过滤用户的输入,使攻击者成功的向服务器提交恶意的 SQL 查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码。
很多 Web 开发者没有意识到 SQL 查询是可以被篡改的,从而把 SQL 查询当作可信任的命令。殊不知,SQL 查询是可以绕开访问控制,从而绕过身份验证和权限检查的。更有甚者,有可能通过 SQL 查询去运行主机系统级的命令。
1. SQL 注入原理
下面将通过一些真实的例子来详细讲解 SQL 注入的方式的原理。
考虑以下简单的管理员登录表单:
复制
<form action="/login" method="POST">
<p>Username: <input type="text" name="username" ></p>
<p>Password: <input type="password" name="password" ></p>
<p><input type="submit" value="登录" ></p>
</form>
复制
复制
后端的 SQL 语句可能是下面这样:
复制
SELECT * FROM user WHERE username='${username}' AND psw='${password}'
-- 接下来就是执行 sql 语句
复制
复制
目的就是来验证用户名和密码是不是正确,按理说乍一看上面的 SQL 语句也没什么毛病,确实是能够达到我们的目的,可是你只是站在用户会老老实实按照你的设计来输入的角度来看问题,如果有一个恶意攻击者输入的用户名是 zhangsan' OR 1 = 1 --
,密码随意输入,就可以直接登入系统了!
冷静下来思考一下,我们之前预想的真实 SQL 语句是:
复制
SELECT * FROM user WHERE username='zhangsan' AND psw='mypassword'
复制
复制
可是,恶意攻击者的奇怪用户名将你的 SQL 语句变成了如下形式:
复制
SELECT * FROM user WHERE username='zhangsan' OR 1 = 1 --' AND psw='xxxx'
复制
在 SQL 中,--
是注释后面的内容的意思,所以查询语句就变成了:复制
复制
SELECT * FROM user WHERE username='zhangsan' OR 1 = 1
复制
这条 SQL 语句的查询条件永远为真,所以意思就是恶意攻击者不用密码,就可以登录账号,然后可以在里面为所欲为,然而这还只是最简单的注入,厉害的 SQL 注入高手甚至可以通过 SQL 查询去运行主机系统级的命令,将主机里的内容一览无余,通过以上的例子,已经了解了 SQL 注入的原理,我们基本已经能找到防御 SQL 注入的方案了。复制
2. 预防 SQL 注入
防止 SQL 注入主要是不能允许用户输入的内容影响正常的 SQL 语句的逻辑,当用户的输入的信息将要用来拼接 SQL 语句的话,我们应该永远选择不相信,任何内容都必须进行转义过滤,当然做到这个还是不够的,下面列出防御 SQL 注入的几点注意事项:
严格限制 Web 应用的数据库的操作权限,给此用户提供仅仅能够满足其工作的最低权限,从而最大限度的减少注入攻击对数据库的危害。
后端代码检查输入的数据是否符合预期,严格限制变量的类型,例如使用正则表达式进行一些匹配处理。
对进入数据库的特殊字符(
'
,"
,\
,<
,>
,&
,*
,;
等)进行转义处理,或编码转换。基本上所有的后端语言都有对字符串进行转义处理的方法。所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中,即不要直接拼接 SQL 语句。
在应用发布之前建议使用专业的 SQL 注入检测工具进行检测,以及时修补被发现的 SQL 注入漏洞。例如开源工具 sqlmap、SQLninja 等。
避免网站打印出 SQL 错误信息,比如类型错误、字段不匹配等,把代码里的 SQL 语句暴露出来,以防止攻击者利用这些错误信息进行 SQL 注入。
不要过于细化返回的错误信息,如果目的是方便调试,就去使用后端日志,不要在接口上过多的暴露出错信息,毕竟真正的用户不关心太多的技术细节,只要话术合理就行。
碰到要操作的数据库的代码,一定要慎重,小心使得万年船,多找几个人多来几次 code review,将问题都暴露出来,而且要善于利用工具,操作数据库相关的代码属于机密,做好团队安全意识提升工作。
四、命令行注入
命令行注入漏洞,指的是攻击者能够通过 HTTP 请求直接侵入主机,执行攻击者预设的 shell 命令,听起来好像匪夷所思,这往往是 Web 开发者最容易忽视但是却是最危险的一个漏洞之一,看一个实例:
假如现在需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去产出一个结果返回给用户,接口的部分实现如下:
复制
// 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repo
const exec = require('mz/child_process').exec;
let params = {/* 用户输入的参数 */};
exec(`git clone ${params.repo} /some/path`);
复制
复制
这段代码确实能够满足业务需求,正常的用户也确实能从指定的 git repo 上下载到想要的代码,可是和 SQL 注入一样,这段代码在恶意攻击者眼中,简直就是香饽饽。
如果 params.repo
传入的是 https://github.com/golang/go.git 当然没问题了。
可是如果 params.repo
传入的是 https://github.com/golang/go.git && rm -rf /* &&
恰好服务是用 root 权限起的就惨了。
具体恶意攻击者能用命令行注入干什么也像 SQL 注入一样,手法是千变万化的,但原理都是一样的。防止命令行注入需要做到以下几件事情:
后端对前端提交内容需要完全选择不相信,并且对其进行规则限制(比如正则表达式)。
在调用系统命令前对所有传入参数进行命令行参数转义过滤。
不要直接拼接命令语句,借助一些工具做拼接、转义预处理,例如 Node.js 的
shell-escape
npm 包。
还是前面的例子,我们可以做到如下:
复制
const exec = require('mz/child_process').exec;
// 借助 shell-escape npm 包解决参数转义过滤问题
const shellescape = require('shell-escape');
let params = {/* 用户输入的参数 */};
// 先过滤一下参数,让参数符合预期
if (!/正确的表达式/.test(params.repo)) {
return;
}
let cmd = shellescape([
'git',
'clone',
params.repo,
'/some/path'
]);
// cmd 的值: git clone 'https://github.com/xx/xx.git && rm -rf / &&' /some/path
// 这样就不会被注入成功了。
exec(cmd);
复制
无论是在何种后端语言环境中,凡是涉及到代码调用系统 shell 命令的时候都一定要谨慎。
复制
五、DDoS 攻击
DDoS 又叫分布式拒绝服务,全称 Distributed Denial of Service,其原理就是利用大量的请求造成资源过载,导致服务不可用。
大多数 DDOS 攻击的潜在有效性来自发起攻击所需的资源量与吸收或防护 攻击所需的资源量之间的差异,危害在于:
网站瘫痪。
无法提供正常网络服务(如:网络游戏)。
1. OSI 7 层模型 &TCP/IP4 层结构
OSI: open system interconnection 开放式系统互联参考模型
OSI 和TCP/IP 的对应关系和协议
2. 网络层攻击
通常通过 TCP/IP 协议簇的漏洞,对目标服务器发送大量数据流,超过设备处理能力或 使网络带宽饱和,以至于网络瘫痪,典型的网络层攻击有:
UDP 泛洪攻击:
DNS 放大攻击:
ICMP 泛洪攻击:
内存缓存 DDOS;
(1)UDP 泛洪攻击
UDP 洪泛攻击是一种拒绝服务攻击,其中大量的用户数据报协议(UDP)数据包被发送到目标服务器,目的是压倒该设备的处理和响应能力。防火墙保护目标服务器也可能因 UDP 泛滥而耗尽,从而导致对合法流量的拒绝服务。
UDP 洪泛攻击主要通过利用服务器响应发送到其中一个端口的 UDP 数据包所采取的步骤。在正常情况下,当服务器在特定端口接收到UDP数据包时,会经过两个步骤:
服务器首先检查是否有任何当前侦听指定端口请求的程序正在运行。
如果该端口上没有程序正在接收数据包,则服务器将以 ICMP (ping) 数据包作为响应, 以告知发送方目标不可达。
防御 UDP 洪泛攻击:
根据域名 IP 自学习结果主动回应,减轻服务器负载(使用 DNS Cache)。
对突然发起大量频度较低的域名解析请求的源 IP 地址进行带宽限制。
在攻击发生时降低很少发起域名解析请求的源 IP 地址的优先级。
限制每个源 IP 地址每秒的域名解析请求次数。
(2)DNS 放大攻击
请求包较小,响应包非常大,黑客使用伪造的请求包请求 DNS 响应,IP 改为受害者 IP。DNS 服务器 向受害者发送大量的包导致而其网络则被虚假流量堵塞。
防御 DNS 放大攻击:
对于运行网站或服务的个人或公司而言,他们的缓解方案非常有限。这是因为尽管个人服务器可能是攻击目标,但并不是容量耗尽攻击主要作用所在的地方。由于攻击产生的大量流量,服务器周围的基础设施会受到影响。Internet 服务提供商(ISP) 或其他上游基础设施提供商可能无法处理传入的流量,变得不堪重负。在这种情况下,该 ISP 可能将所有流量传送到目标受害者的 IP 地址,保护自己,并使目标的网站离线。除 Cloudflare DDoS 保护之类的异地保护服务外,缓解策略主要是预防性 Internet 基础设施解决方案。
减少开放 DNS 解析器的总数
DNS 放大攻击的一个重要组成部分是对开放 DNS 解析器的访问权限。如果 Internet 上有配置不当的 DNS 解析器,那么攻击者仅仅需要找到这种 DNS 解析器即可利用。理想情况下,DNS 解析器应仅向源自受信任域名的设备提供服务。对于基于反射的攻击,开放DNS解析器将响应 Internet 上任何位置的查询,因此有可能被利用。限制 DNS 解析器,使其仅响应来自受信任来源的查询,即可使服务器无法被用于任何类型的放大攻击。
源 IP 验证 - 阻止欺骗性数据包离开网络
由于攻击者的僵尸网络发送的 UDP 请求必须具有指向受害者 IP 地址的欺骗性源 IP 地址,因此,要降低基于 UDP 的放大攻击的有效性,其关键在于 Internet 服务提供商 (ISP)拒绝任何具有欺骗性 IP 地址的内部流量。如果有数据包从网络内部发送,但其源地址看似源于网络外部,则可能是欺骗性的数据包,可以将其丢弃。Cloudflare 强烈建议所有提供商实施入口筛选,并且会不时联系不知情地参与 DDoS 攻击的 ISP 并帮助他们意识到漏洞。
(3)ICMP 泛洪攻击
ICMP 泛洪攻击:当 ICMP ping 产生的大量回应请求超出了系统的最大限度,以至于系统耗费所有资源来进行响应直至再也无法处理有效 的网络信息流,这就是 ICMP 洪水攻击。简单说攻击者向一个子网的广播地址发送多个ICMP Echo请求数据包。并将源地址伪装成想要攻击的目标主机的地址。然后该子网上的所有主机均会对此ICMP Echo请求包作出答复,向被攻击的目标主机发送数据包,使此主机受到攻击,导致网络阻塞。ICMP Flood攻击主要的目的使网络瘫痪,这也是最常见和最常用的网络攻击行为之一。
ICMP实质是控制信息协议,一般位于IP层,主要通过含有ICMP功能的主机与路由器之间发送ICMP数据包,来达到实现信息查询和错误通知的功能。因此攻击者利用icmp获取主机信息,时间、路由信息等。所以为攻击者创造了极大得便利条件。常利用ICMP攻击的操作有:利用ICMP echo数据包进行DDOS攻击;利用ICMP定向进行IP欺骗和窃听;利用ICMP的路由器信息绕过防火墙进行远程控制。
Ping 洪水的破坏效果与对目标服务器发出的请求数量成正比。
防御 ICMP 泛洪攻击:
在路由器上对 ICMP 数据包进行带宽限制,将 ICMP 占用的带宽控制在一定的范围内,这样即使有 ICMP 攻击,它所占用的带宽也是非常有限的,对整个网络的影响非常少;
在主机上设置 ICMP 数据包的处理规则,最好是设定拒绝所有的 ICMP 数据包。
设置ICMP数据包处理规则的方法:
在操作系统上设置包过滤。
在主机上安装防火墙。
(4)内存缓存 DDOS
内存缓存分布式拒绝服务 (DDoS) 攻击是一种网络攻击,攻击者试图使目标受害者的网络流量超载。攻击者将欺骗性的请求发送到易受攻击的 UDP 内存缓存服务器,该服务器随后向目标受害者发送 Internet 流量,从而可能使受害者的资源不堪重负。当目标的 Internet 基础设施过载时,就无法处理新请求,而常规流量也无法访问Internet 资源,从而导致拒绝服务。
内存缓存攻击的工作方式类似于所有 DDoS 放大攻击,例如 NTP 放大和 DNS 放大。这种攻击欺骗性请求发送到易受攻击的服务器,该服务器随后会发出比初始请求大的数据量作为响应,因此放大了流量。
内存缓存放大攻击就好比是一个心怀恶意的青少年打电话给一家餐厅说“我要菜单上的东西每样来一份,请给我回电话并告诉我整个订单的信息”。当餐厅询问回叫号码时,他却给出目标受害者的电话号码。然后,目标会收到来自餐厅的呼叫,接到他们未请求的大量信息。
这种放大攻击的方法之所以成为可能,因为内存缓存服务器可以选择使用 UDP 协议进行操作。UDP 是一种网络协议,允许在不首先获得所谓握手的情况下发送数据 - 握手是指双方都同意通信的网络过程。之所以使用 UDP,是因为不用咨询目标主机是否愿意接收数据,无需事先征得它们的同意,就可以将大量数据发送给目标主机。
内存缓存攻击分为 4 个步骤:
攻击者将大量数据有效载荷*植入暴露的内存缓存服务器上。
接下来,攻击者使用目标受害者的 IP 地址伪造 HTTP GET 请求。
带有漏洞的内存缓存服务器接收到请求,试图通过响应来提供帮助,因此将大量响应发送到目标。
目标服务器或其周围的基础设施无法处理从内存缓存服务器发送的大量数据,因此导致过载和对正常请求拒绝服务。
防御内存缓存攻击:
禁用 UDP - 对于内存缓存服务器,请确保在不需要时禁用 UDP 支持。默认情况下,内存缓存启用了 UDP 支持,这可能会使服务器容易受到攻击。
对内存缓存服务器进行防火墙保护 - 通过在内存缓存服务器和 Internet 之间添加防火墙保护,系统管理员可以根据需要使用 UDP,而不必暴露于风险中。
防止 IP 欺骗 - 只要可以伪造 IP 地址,DDoS 攻击就可以利用此漏洞将流量定向到受害者的网络。防止 IP 欺骗是一个规模较大的解决方案,无法由特定的系统管理员实施,它要求传输提供商禁止源 IP 地址源自网络外部的任何数据包离开其网络。换句话说,Internet 服务提供商 (ISP) 之类的公司必须筛选流量,以使离开其网络的数据包不得假装成来自其他地方的其他网络。如果所有主要的传输提供商都实施了这种筛选,基于欺骗的攻击将在一夜之间消失。
开发具有减少 UDP 响应的软件 - 消除放大攻击的另一种方法是去除任何传入请求的放大因素;如果由于 UDP 请求而发送的响应数据小于或等于初始请求,则放大就不复可能。
3. 传输层攻击
通常通过 TCP 协议的漏洞,对目标服务器发送大量数据流,使其网络带宽 饱和或连接资源耗尽,以至于网络瘫痪,典型的网络层攻击有:
SYN 泛洪攻击
ACK 泛洪攻击
(1)TCP 连接的建立
TCP与UDP不同,它是基于连接的,为了在服务端和客户端之间传送TCP数据,必须先建立一个虚拟电路,也就是TCP连接。也就是我们经常听说的TCP协议中的三次握手(Three-way Handshake),建立 TCP 连接的标准过程如下:
首先,客户端发送一个包含SYN标志的TCP报文,SYN即同步(Synchronize),同步报文会指明客户端使用的端口以及TCP连接的初始序号。
其次,服务器在收到客户端的SYN报文后,将返回一个SYN+ACK(即确认Acknowledgement)的报文,表示客户端的请求被接受,同时TCP初始序号自动加一。
最后,客户端也返回一个确认报文ACK给服务器端,同样TCP序列号被加一,到此一个TCP连接完成。下面的动态图很直观的描述了 TCP 连接建立的过程。
(2)SYN 泛洪攻击
SYN 泛洪攻击是 DoS (拒绝服务攻击)与 DDoS (分布式拒绝服务攻击)的方式之一,它是利用 TCP 协议缺陷,发送大量伪造的 TCP 连接请求,从而使得被攻击方资源耗尽(CPU 满负荷或内存不足)的攻击方式,最终导致系统或服务器宕机。
SYN 泛洪攻击攻击正是利用了 TCP 连接的三次握手,假设一个用户向服务器发送了 SYN 报文后突然死机或掉线,那么服务器在发出 SYN+ACK 应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送 SYN+ACK 给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为 SYN Timeout,一般来说这个时间是分钟的数量级(大约为 30 秒-2 分钟)。
一个用户出现异常导致服务器的一个线程等待1分钟并不会对服务器端造成什么大的影响,但如果有大量的等待丢失的情况发生,服务器端将为了维护一个非常大的半连接请求而消耗非常多的资源。我们可以想象大量的保存并遍历也会消耗非常多的 CPU 时间和内存,再加上服务器端不断对列表中的 IP 进行 SYN+ACK 的重试,服务器的负载将会变得非常巨大。
如果服务器的 TCP/IP 栈不够强大,最后的结果往往是堆栈溢出崩溃。相对于攻击数据流,正常的用户请求就显得十分渺小,服务器疲于处理攻击者伪造的TCP 连接请求而无暇理睬客户的正常请求,此时从正常客户会表现为打开页面缓慢或服务器无响应,这种情况就是我们常说的服务器端 SYN 泛洪攻击。
防御 SYN 泛洪攻击:
第一种是缩短 SYN Timeout 时间,由于 SYN 泛洪攻击的效果取决于服务器上保持的 SYN 半连接数,这个值 =SYN 攻击的频度 x SYN Timeout,所以通过缩短从接收到 SYN 报文到确定这个报文无效并丢弃改连接的时间,例如设置为 20 秒以下,可以成倍的降低服务器的负荷。但过低的 SYN Timeout 设置可能会影响客户的正常访问。
第二种方法是设置 SYN Cookie,就是给每一个请求连接的 IP 地址分配一个 Cookie,如果短时间内连续受到某个 IP 的重复 SYN 报文,就认定是受到了攻击,并记录地址信息,以后从这个 IP 地址来的包会被一概丢弃。这样做的结果也可能会影响到正常用户的访问。
上述的两种方法只能对付比较原始的 SYN 泛洪攻击,缩短 SYN Timeout 时间仅在对方攻击频度不高的情况下生效,SYN Cookie 更依赖于对方使用真实的 IP 地址,如果攻击者以数万/秒的速度发送 SYN 报文,同时利用 SOCK_RAW 随机改写IP报文中的源地址,以上的方法将毫无用武之地。
(2)ACK 泛洪攻击
ACK 泛洪攻击是指攻击者通过使用 TCP ACK 数据包使服务器过载。像其他 DDoS 攻击一样,ACK 泛洪攻击的目的是通过使用垃圾数据来减慢攻击目标的速度或使其崩溃,从而导致拒绝向其他用户提供服务。目标服务器被迫处理接收到的每个 ACK 数据包,消耗太多计算能力,以至于无法为合法用户提供服务。
利用合法和非法 ACK 数据包看起来基本相同的特性,进行 DDOS 攻击,不易被外部安全设备拦截的特性,针对于服务器和防火墙的攻击。
4. 应用层攻击
通常通过 HTTP 协议或者容器的漏洞,对目标服务器发送少量数据流,使 其连接资源耗尽,从而拒绝服务,典型的应用层攻击有:
Slowloris 攻击
HTTP Post DDOS
HTTP 泛洪(CC 攻击)
(1)Slowloris 攻击
Slowloris 攻击也称为 Slowloris 拒绝服务攻击,一种慢速连接攻击。是利用Http协议的漏洞或设计缺陷,直接造成拒绝服务。
攻击原理:
通过极低的速度往服务器发送HTTP请求。由于Web服务器对于并发的连接数都有一定的上限,因此若是恶意地占用住这些连接不释放,那么Web Server的所有连接都将被恶意连接占用,从而无法接受新的请求,导致拒绝服务。
防御 Slowloris 攻击:
统计每个 TCP 连接的时长并计算单位时间内通过的报文数量即可做精确识别。一个 TCP 连接中,HTTP 报文太少和报文太多都是不正常的,过少可能是慢速连接攻击,过多可能是使用 HTTP 1.1 协议进行的 HTTP泛洪攻击,在一个 TCP 连接中发送多个 HTTP 请求。
限制 HTTP 头部传输的最大许可时间。超过指定时间 HTTP Header 还没有传输完成,直接判定源IP地址为慢速连接攻击,中断连接并加入黑名单。
(2)HTTP Post DDOS
与 Sloworis 相似,指定一个比较大的 content-length,然后以很低的速度发包,如一 分钟一个字节,保持住连接。当多台机器这样连接,耗尽服务器连接资源,造成拒绝服务。
攻击特点:
它可以针对任意 Web 服务。HTTP 协议在接收到 request 之前是无法对请求内容作校验的,所以即使你的 Web 应用没有可用 form 表单,这个攻击一样有效。
廉价。在客户端以单线程方式建立较大数量的无用连接,并保持持续发包的代价非常低廉。实际试验中一台普通 PC 可以建立的 Socket 连接在 3000 个以上。这对一台普通的 web server,将是致命的打击。更不用说结合肉鸡群做分布式 DOS(拒绝服务)了。
防御 HTTP Post DDOS
检查日志,查找类似的错误报警:
复制
[error] server reached MaxClients setting, consider raising the MaxClients setting
复制
看看有没有被这种攻击盯上。复制
调整防火墙设置。有条件的,在IPS上做一下规则设置。
(3)HTTP 泛洪(CC 攻击)
HTTP 泛洪攻击并不需要控制大批的肉鸡,取而代之的是通过端口扫描程序在互联网上寻找匿名的 HTTP 代理或者 SOCKS 代理,攻击者通过匿名代理对攻击目标发起 HTTP 请求。伪装成正常的用户进行站点的请求,通过巨大的连接数来消耗站点资源。简而言之就是,黑客发送的正常的(GET POST)请求,针对于服务器需要消耗大量资源的页面,如 账号登录,搜索等功能,造成服务器资源耗尽,无法响应正常连接。
攻击方式:
HTTP GET攻击 – 在这种形式的攻击中,协调多台计算机或其他设备以从目标服务器发送对图像,文件或某些其他资源的多个请求。当目标被传入的请求和响应淹没时,来自合法流量源的其他请求将发生拒绝服务。
HTTP POST攻击 – 通常在网站上提交表单时,服务器必须处理传入的请求并将数据推送到持久层,通常是数据库。与发送POST请求所需的处理能力和带宽量相比,处理表单数据和运行必要的数据库命令的过程相对密集。此攻击利用相对资源消耗的差异,通过将许多发布请求直接发送到目标服务器,直到其容量饱和并发生拒绝服务。
防御 HTTP 泛洪攻击
CC 攻击的防御必须要结合实际业务情况,对实际业务构建系统的防御模型,如:连接特征模型、业务访问特征模型、客户端行为模型等,接收请求端统计客户信息并依据模型特征进行处理,包括:用户黑名单限制、限制访问速率、随机丢弃请求等。
对于流行的 DDoS/CC 流量型攻击,DDoS 高防服务可以通过云端清洗集群、数据库监控牵引系统等技术进行防护。
六、流量劫持
流量劫持应该算是黑产行业的一大经济支柱了,流量劫持基本分两种:DNS 劫持
和 HTTP 劫持
,目的都是一样的,就是当用户访问网站的时候,给你展示的并不是或者不完全是真实目标网站提供的“内容”。
1. DNS 劫持
DNS 劫持,也叫做域名劫持,可以这么理解,「你打了一辆车想去商场吃饭,结果你打的车是小作坊派来的,直接给你拉到小作坊去了」,DNS 的作用是把网络地址域名对应到真实的计算机能够识别的 IP 地址,以便计算机能够进一步通信,传递网址和内容等。如果当用户通过某一个域名访问一个站点的时候,被篡改的 DNS 服务器返回的是一个恶意的钓鱼站点的 IP,用户就被劫持到了恶意钓鱼站点,然后继而会被钓鱼输入各种账号密码信息,泄漏隐私。
这类劫持,要不就是网络运营商搞的鬼,一般小的网络运营商与黑产勾结会劫持 DNS,要不就是电脑中毒,被恶意篡改了路由器的 DNS 配置,基本上做为开发者或站长却是很难察觉的,除非有用户反馈,现在升级版的 DNS 劫持还可以对特定用户、特定区域等使用了用户画像进行筛选用户劫持的办法,另外这类广告显示更加随机更小,一般站长除非用户投诉否则很难觉察到,就算觉察到了取证举报更难。无论如何,如果接到有 DNS 劫持的反馈,一定要做好以下几件事:
取证很重要,时间、地点、IP、拨号账户、截屏、URL 地址等一定要有。
可以跟劫持区域的电信运营商进行投诉反馈。
如果投诉反馈无效,直接去工信部投诉,一般来说会加上你的域名。
2. HTTP 劫持
大家平时上网的时候,在网页的一脚有时候会出现一些小广告,有时候这些广告,不是访问的站点为了盈利而投放的广告,而是第三方的运营商提供的。一般来说 HTTP劫持主要通过下面几个步骤来做:
标识 HTTP 连接。在各种连接中,有许多种协议,第一步做的就是在 TCP 连接中,找出应用层采用了 HTTP 协议的连接,进行标识。
篡改 HTTP 响应体,可以通过网关来获取数据包进行内容的篡改。
抢先回包,将篡改后的数据包抢先正常站点返回的数据包先到达用户侧,这样后面正常的数据包在到达之后会被直接丢弃。
防御 HTTP 劫持:
事前加密
HTTPS 协议就是一种基于 SSL 协议的安全加密网络应用层协议,可以很好的防止 HTTP 劫持。很大一部分 HTTP 劫持,主要的原因就是在传输数据时都是明文的,使用了 HTTPS 后,会在 HTTP 协议之上加上 TLS 进行保护,使得传输的数据进行加密,但是使用 HTTPS,一定要注意规范,必须要全站使用 HTTPS,否则只要有一个地方没有使用 HTTPS,明文传输就很有可能会被 HTTP 劫持了。
事中规避
在 HTTP 劫持的步骤中,第一步是标记 TCP 连接,因此只要躲过了标识,那么后续的运营商篡改就不会存在了,有一种方式就是拆分 HTTP 请求拆分数据包就是把 HTTP 请求的数据包拆分成多个,运营商的旁路设备由于没有完整的 TCP/IP 协议栈,所以就不会被标志,而目标 web 服务器是有完整的 TCP/IP 协议栈,能接收到的数据包拼成完整的 HTTP 请求,不影响服务。
事后屏蔽
通过浏览器 api,根据若干规则去匹配DOM中的节点,对匹配到的节点作拦截和隐藏:CSP(内容安全策略),DOM 事件监听等。CSP 是浏览器附加的一层安全层,用于对抗跨站脚本与数据注入,运营商植入内容性质与数据注入类似,因此,可以用 CSP 对抗运营商劫持。通过在 HTTP 响应头或 meta 标签设置好规则,支持拦截和上报劫持信息的功能。
DOM 事件监听主要是监听 DOMNodeInserted、DOMContentLoaded、DOMAttrModified 等事件,可以在前端 DOM 结构发生变化时触发回调,这时补充一些检测逻辑,即可判断是不是业务的正常UI逻辑,如果不是,即可认为是来自劫持。