CVE-2021-22876: Automatic referer leaks credentials
Low
C
curl
Submitted None
Actions:
Reported by
vsz
Vulnerability Details
Technical details and impact analysis
## Summary:
When using the `--referer ';auto'` feature the current URL is copied as-is to the referrer header of the subsequent request. The recommendation [1] is to strip these (along with the URL fragment). I can imagine this may, in rare cases, result in unwanted/unexpected disclosure of credentials (e.g. them appearing in 3rd party web server logs), though the overall chances seem low (also considering that ';auto', by hunch, is likely not a widely used curl feature).
[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer#directives
## Steps To Reproduce:
```
$ curl -svLe ';auto' 'https://user:[email protected]#frag' 2>&1 >/dev/null | grep -i Referer:
```
## Supporting Material/References:
```
$ curl -V
curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2
Release-Date: 2019-03-27
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets
```
## Patch that fixes it
```diff
diff --git a/lib/transfer.c b/lib/transfer.c
index c3b2d11a2..f63aadbaf 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1567,6 +1567,9 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->state.followlocation++; /* count location-followers */
if(data->set.http_auto_referer) {
+ CURLU *h;
+ char *url;
+
/* We are asked to automatically set the previous URL as the referer
when we get the next URL. We pick the ->url field, which may or may
not be 100% correct */
@@ -1576,7 +1579,40 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->change.referer_alloc = FALSE;
}
- data->change.referer = strdup(data->change.url);
+ /* Make a copy of the URL without the crenditals and fragment */
+ h = curl_url();
+ if(!h)
+ return CURLE_OUT_OF_MEMORY;
+
+ uc = curl_url_set(h, CURLUPART_URL, data->change.url, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ uc = curl_url_get(h, CURLUPART_URL, &url, 0);
+ if(uc) {
+ curl_url_cleanup(h);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ curl_url_cleanup(h);
+
+ data->change.referer = url;
if(!data->change.referer)
return CURLE_OUT_OF_MEMORY;
data->change.referer_alloc = TRUE; /* yes, free this later */
```
I'm ready to continue this in a public PR if it seems more fitting.
## Impact
The best I can think of is if an attacker gets hold of web server logs that includer referrer info with credentials leaked into them. It's a privacy/sensitive info-leak vulnerability at best. Can't readily think of a way to actively exploit this.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved