报告摘要
libcurl的libssh后端在实现CURLOPT_SSH_AUTH_TYPES选项时,未能正确处理CURLSSH_AUTH_AGENT标志。具体来说,如果仅设置了CURLSSH_AUTH_PUBLICKEY,实现会表现得像CURLSSH_AUTH_AGENT总是被隐式定义一样。因此,身份验证时不再需要密钥密码短语。
结果就是,即使用户运行的应用程序专门没有设置CURLSSH_AUTH_AGENT,只要用户有ssh-agent/pageant在运行,使用libcurl的应用程序仍会使用ssh-agent/pageant进行身份验证,从而绕过需要知道密钥密码短语的要求。
影响版本
libcurl 8.17.0
复现步骤
- 配置并构建带有
--with-libssh选项的libcurl。 - 编译以下概念验证应用程序:
1 2 3 4 5 6 7 8 9 10 11 12 13#include <curl/curl.h> int main(void) { CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_URL, "sftp://host.example/"); curl_easy_setopt(curl, CURLOPT_SSH_AUTH_TYPES, CURLSSH_AUTH_PUBLICKEY); curl_easy_perform(curl); curl_easy_cleanup(curl); } return 0; } - 让当前用户在
host.example上拥有账户。为用户设置SSH密钥密码短语。将用户SSH公钥添加到host.example用户的~/.ssh/authorized_keys文件中。运行ssh-agent并添加用户的密钥。 - 执行概念验证应用程序。
结果:应用程序在不需要SSH密钥密码短语的情况下,即可认证到host.example。
支持材料/参考文献
- libcurl代码调用libssh
ssh_userauth_publickey_auto:GitHub链接 - libssh
ssh_userauth_publickey_auto代码与ssh-agent交互:GitHub链接
影响
摘要:绕过了SSH密钥密码短语要求。
讨论时间线
- 报告人 (nyymi):在漏洞提交后补充说明,尽管用户需要运行代理并输入密码短语(这很常见),但在某些场景下问题会变得严重。例如,某些应用程序可能出于某种原因(比如希望每次认证都要求用户输入密钥密码短语作为第二因素)特意不希望使用代理。在这种情况下,对于libssh后端,这个第二因素(密码短语)会被绕过。
- curl维护者 (bagder):将严重性更新为低。认为虽然有影响,但由于用户在其他地方已经持有密码短语,问题并不严重。随后将状态改为 “已分类”。
- curl维护者 (jimfuller2024):确认了报告,并指出该漏洞可能允许用户使用其已拥有的有效凭据成功进行身份验证,但不允许未经授权的用户进行冒充或远程执行。由于攻击者已经处于受信任的上下文中(代理运行,密码短语已输入),感觉更多是带来不便,但可能在链式攻击中被利用,因此也认为是低危级别。
- 维护者分配了CVE编号:CVE-2025-15224。
修复尝试与讨论
-
初始修复提议:维护者提出了一个看似最小的修复,在
lib/vssh/libssh.c中添加条件判断,仅当设置了CURLSSH_AUTH_AGENT时才调用ssh_userauth_publickey_auto。1 2 3 4 5 6 7 8 9 10 11 12 13--- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -974,11 +974,11 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data, return rc; } myssh_to(data, sshc, SSH_AUTH_PKEY); } - else { + else if(data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) { rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL, data->set.ssl.key_passwd); if(rc == SSH_AUTH_AGAIN) return SSH_AGAIN;报告人反馈:这个修复会导致当
CURLSSH_AUTH_AGENT未设置时,代码永远卡在SSH_AUTH_PKEY_INIT状态,因为没有任何认证操作被执行。 -
替代方案提案:报告人提出了更全面的修复方案,在尝试公钥认证之前,检查是否提供了私钥文件路径或设置了
CURLSSH_AUTH_AGENT标志。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c index 5d5125b526..bde6355f73 100644 --- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -921,7 +921,11 @@ static int myssh_in_AUTHLIST(struct Curl_easy *data, "keyboard-interactive, " : "", sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD ? "password": ""); - if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { + /* For public key auth we need either the private key or + CURLSSH_AUTH_AGENT. */ + if((sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) && + (data->set.str[STRING_SSH_PRIVATE_KEY] || + (data->set.ssh_auth_types & CURLSSH_AUTH_AGENT))) { myssh_to(data, sshc, SSH_AUTH_PKEY_INIT); infof(data, "Authentication using SSH public key file"); }潜在影响:此修复会导致libssh后端在未指定
CURLOPT_SSH_PRIVATE_KEYFILE且未设置CURLSSH_AUTH_AGENT标志时直接失败,而不是像libssh2后端那样尝试查找并使用默认的$HOME/.ssh/id_*密钥(前提是密钥无密码)。报告人将其视为libssh API的一个限制,建议就此处理。 -
CWE分类讨论:维护者最初建议CWE-1023(与缺失因素的不完全比较),但另一位维护者指出问题不在于比较操作不正确,而在于应用程序逻辑完全忽略了配置状态,因此更倾向于使用描述由此产生的安全弱点的CWE-287(身份验证机制不正确)。
-
修复实施:维护者采纳了报告人的替代方案,并创建了修复拉取请求 #20110。
后续处理
- 维护者通知了distros@openwall邮件列表关于此问题、其待发布状态以及相关的即将发布的版本。
- 报告状态最终被标记为 “已解决” 并 “已公开”。
- 该漏洞不符合curl项目的赏金条件(奖励由互联网漏洞赏金计划管理),但报告人可以向其提交奖励申请。
报告信息
- 报告ID: #3480925
- 报告日期: 2025年12月28日 UTC 21:22
- 报告人: nyymi
- 报告对象: curl
- 状态: 已解决
- 严重性: 低 (0.1 ~ 3.9)
- 披露日期: 2026年1月7日 UTC 08:03
- CVE ID: CVE-2025-15224
- 赏金: 无