curl · Report #3480925
CVE-2025-15224: libssh key passphrase bypass without agent set
How it was found
Summary:
libcurl libssh backend CURLOPT_SSH_AUTH_TYPES doesn't implement CURLSSH_AUTH_AGENT flag correctly. Rather if CURLSSH_AUTH_PUBLICKEY is set, the implementation acts as if CURLSSH_AUTH_AGENT is always implicitly defined, and thus no key passphrase is required for authentication.
As a result if the user has ssh-agent /pageant running, libcurl using application that specifically does not set CURLSSH_AUTH_AGENT will still use the ssh-agent / pageant for authentication bypassing the requirement for knowing the key passphrase.
Affected version
8.17.0
Steps To Reproduce:
- Configure and build libcurl with
--with-libssh - Compile the following proof-of-concept app:
#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;
}
- Have the current user have account on
host.example. Have a passphrase set for the user's ssh key. Have the ssh key pubkey added to thehost.exampleusers~/.ssh/authorized_keys. Have ssh-agent running with the user's key added. - Execute the proof of concept application.
As a result the application authenticates to the host.example without needing the ssh key passphrase.
Supporting Material/References:
- libcurl code calling libssh
ssh_userauth_publickey_auto: https://github.com/curl/curl/blob/5c0cdd26d66342efaaf2685f2a539be5db21cacd/lib/vssh/libssh.c#L980 - libssh
ssh_userauth_publickey_autocode talking to ssh-agent: https://github.com/libssh/libssh-mirror/blob/ac6d2fad4a8bf07277127736367e90387646363f/src/auth.c#L1120
Impact
Summary:
Bypassing the SSH key passphrase requirement.