原文地址:https://www.thezdi.com/blog/2019/12/4/cve-2019-9512-a-microsoft-windows-http2-ping-flood-denial-of-service

在这篇趋势科技漏洞研究服务(Trend Micro Vulnerability Research Service)的漏洞报告的摘录中,趋势科技研究团队的Saran Neti 和 Dusan Stevanovic详细介绍了最近的一个Windows的IIS服务的未授权拒绝服务攻击。下面那是他们关于CVE-2019-9512的报告的一部分,只做了很少的修改。


最近,Windows系统中发现了一个拒绝服务攻击漏洞。该漏洞是由于不断向web服务器发送HTTP/2 Ping帧(不要与ICMP Ping混淆)而导致资源耗尽。这个问题最初是由Netflix的Jonathan Looney报告给微软的,并由CVE-2019-9512解决。
一个未经授权的远程攻击者可疑通过发送大量的HTTP/2 的ping帧来利用此漏洞。而一旦利用成功,将会目标系统拒绝服务。

漏洞详情

Windows Internet Information Server (IIS)是预装在Windows操作系统中的Internet服务的集合。IIS包括一个HTTP服务器,它既可以提供静态内容,也可以提供动态内容。IIS支持各种web技术,包括HTML、ASP、ASP.NET、JSP、PHP和CGI。同时IIS也支持新版本的HTTP协议:HTTP/2。这个功能由内核模式驱动程序 http.sys 提供支持。
HTTP/2是超文本传输协议的现代标准。它改进了广泛使用的HTTP/1.1标准,提供了新的特性:用于未来扩展的HTTP版本协商、使用加权流多路复用多个请求以及HTTP头文件的数据压缩。HTTP/2是一个二进制协议,它保留了HTTP/1.1的大部分用法和语义,包括方法、状态码和头字段。现代浏览器(如Google Chrome、Mozilla Firefox和Microsoft Edge)和web服务器(如Microsoft IIS、nginx、Apache httpd)都支持HTTP/2。虽然HTTP/2并不强制要求使用安全的基于TLS的传输,但是这些实现只允许在TLS上使用HTTP/2。应用层协议协商(ALPN) TLS扩展在TLS握手中被端点用来协商应用层协议,它目前包括:HTTP/1.1、SPDY/2、SPDY/3和各种HTTP/2标识符(h2、h2-17、h2-14、h2c、h2c-17)。Microsoft IIS支持h2 ALPN扩展,其中HTTP/2数据在TLS握手完成后立即交换。

HTTP/2连接以24字节的连接开始:

  1. PRI * HTTP/2.0\x0d\x0a\x0d\x0aSM\x0d \x0a\x0d\x0a

接下来是一系列帧的交换,这是HTTP/2中编码数据的基本单元,从设置帧开始。所有帧都有一个固定长度的9字节头,然后是一个可变长度的有效载荷。框架结构如下:
翻译|CVE-2019-9512 Windows HTTP/2 ping泛洪拒绝服务 - 图1

所有多字节整数都是大端字节格式。
HTTP/2 Ping帧(帧类型为 0x6)是一种用于测量来自发送方的最小往返时间,以及确定空闲连接是否仍然有效的机制。Ping帧可以从任何端点发送。除了帧头之外,Ping帧还必须在有效负载中包含8个字节的数据。发送方可以选择发送任何值。不包含ACK标志的Ping帧的接收者必须发送一个设置了ACK标志的Ping帧作为响应,并使用相同的负载。Ping响应应该比其他任何帧具有更高的优先级。Ping帧不与任何单独的流相关联,它们的流标识符应该设置为0。
Windows内核模式HTTP驱动程序 http.sys存在拒绝服务漏洞。当基于windows的web服务器(如IIS)配置为HTTPS时,它默认支持HTTP/2,并使用http.sys处理传入的基于TLS的HTTP/2请求。对于每一个HTTP/2连接, http.sys维持一个状态。当http.sys收到一个ping帧,将调用函数 HTTP!UxDuoParsePing() 来构建这种状态并分配内存。内存分配发生在函数 HTTP! uxdoallocateparcel() 中,该函数是从 HTTP!UxDuoParsePing() 中调用的。如果恶意攻击者发送连续的Ping帧流,就会为处理这些帧分配大量资源。额外的内存也在 HTTP!UxDuoParse()函数中分配,该函数调用 HTTP!UxDuoParsePing()。由于函数 HTTP!UxDuoParsePing()不允许对从客户端接受和处理的Ping帧的数量进行速率限制,因此会导致严重的资源耗尽。
请注意,在修补过的 http.sys 版本中,函数 HTTP!UxDuoParsePing() 将会调用新引入的一个函数 HTTP!UxDuoApplyPingFrameDosPrevention() 。这个新引入的函数利用注册表设置 HTTP2MaxPingsPerMinute ,它限制了客户机在服务器关闭连接之前每分钟可以发送到服务器的最大ping帧数量。此键位于下面的注册表中, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters 。通过发送连续的HTTP/2帧流,攻击者可以导致受影响的目标服务器上的大量资源耗尽,从而导致潜在的拒绝服务状态——特别是在目标机器部署在分布式网络时。

源码

下面的代码片段取自10.0.14393.2828版本 http.sys 。趋势科技安全研究增加的评论已经被强调。
翻译|CVE-2019-9512 Windows HTTP/2 ping泛洪拒绝服务 - 图2

为了触发该条件,攻击者启动与目标服务器的TLS连接,并使用h2 ALPN扩展值协商HTTP/2。然后攻击者向目标主机发送HTTP/2初始字节和多个Ping帧。在攻击者保持连接的期间内,当服务器处理这些帧时,将触发此漏洞。

补丁

微软在8月份发布了针对该漏洞的补丁,并将其指定为CVE-2019-9512。除了应用供应商提供的补丁之外,管理员还需要配置他们的服务器来限制接受的HTTP/2包的数量。这可以根据每个服务器上运行的环境和服务而有所不同。管理员必须在注册表编辑器中添加 HTTP2MaxPingsPerMinute 设置。位置位于 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters 。有关其他信息,请参见供应商的建议。不幸的是,微软没有提供设置该值的指导。

特别感谢趋势科技研究团队的Saran Neti和Dusan Stevanovic对这个漏洞进行了如此彻底的分析。更加详细的分析可疑在这里找到http://go.trendmicro.com/tis/