Slowloris DoS攻击剖析——最酷的应用层拒绝服务攻击

本文深入解析Node.js中的Slowloris DoS漏洞(CVE-2018-12122和CVE-2019-5739),详细讲解这种仅需几千字节数据就能使网站瘫痪的应用层攻击原理、修复方案及其绕过方法。

Slowloris DoS攻击剖析——最酷的应用层拒绝服务攻击

在这篇文章中,我将介绍一个并非由我发现但非常值得分享的漏洞,因为我认为这是一个非常有趣的安全问题。

引言

2018年11月28日,Node.js中披露了一个Slowloris拒绝服务漏洞(CVE-2018-12122)。该漏洞最初由Hackerone上的underflow0报告,并在几个月后被认定已修复。2018年12月1日,mpracucci发现了修复方案的绕过方法,该绕过被分配了CVE-2019-5739。

什么是Slowloris DoS?

拒绝服务攻击旨在破坏目标的可用性。大多数此类攻击依赖于向带宽小于攻击者的服务器发送大量数据,导致目标对合法用户不可用。

这种拒绝服务攻击并不特别有趣,公司通常不会在其漏洞赏金计划中接受此类错误。

Slowloris变体的拒绝服务攻击与传统容量型攻击采用完全相反的方法。作为应用层DoS,它通过非常缓慢地发送请求头,仅用几千字节数据就能使易受攻击的网页瘫痪。

为什么Node.js会受到影响?

旧版本的Apache曾为每个连接分配一个线程/工作进程,并且为了不耗尽系统资源,可用线程数量是有限的。如果攻击者发起大量这种非常慢的线程攻击,服务器将达到其线程限制,网站将对合法用户无响应。

在Node.js中,Slowloris攻击导致可用性问题的原因不同。Node不会为每个新连接创建新线程。相反,请求由单个线程处理,该线程不专用于某个连接,这意味着当连接等待更多数据时,线程可以自由服务其他请求。

由于这种架构,数千个慢连接不会阻止新连接的到来,然而,每个打开的套接字都会消耗一定量的内存。网络套接字还需要自己的文件描述符,每个操作系统对每个进程允许的文件描述符数量都有自己的限制(Linux上为1024)。

这意味着数千个同时的慢连接仍会导致服务器由于高系统资源使用或文件描述符过度使用而变得无响应。

原始修复方案

当CVE-2018-12122被报告时,Node.js实现了一个server.headersTimeout属性,使用Node.js编写Web应用程序的开发人员可以在其中指定一个合理的时间值,在该时间内应发送所有请求头。这将缓解该漏洞,因为请求头不能缓慢发送以使服务器等待。

修复方案的绕过

尽管对CVE-2018-12122的修复确实缓解了原始问题,但后来发现了绕过方法。

通常,当服务器和客户端之间交换多个请求时,会为每个请求创建新的TCP连接。请求头"Connection: keep-alive"告诉服务器在请求和响应后保持TCP连接打开,允许后续HTTP请求重用它。

在Node.js上,确保头发送时间不超过server.headersTimeout中指定值的时间计数器仅适用于给定TCP连接的第一个请求。考虑到这一点,绕过原始修复很简单:

  1. 攻击者发送带有"Connection: keep-alive"头的正常请求
  2. 攻击者可以比选定的头超时更慢地发送第二个请求的头

最终修复方案

为了完全修复此问题,现在在请求后重置时间计数器并重新启动,无论是有新的TCP连接还是重用旧的连接。

影响

此攻击导致拒绝服务。真实用户无法浏览网页,严重损害了可用性。

CVSS评分

高 7.5

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计