7.8 High
CVSS3
Attack Vector
LOCAL
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
4.6 Medium
CVSS2
Access Vector
LOCAL
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
PARTIAL
Availability Impact
PARTIAL
AV:L/AC:L/Au:N/C:P/I:P/A:P
0.001 Low
EPSS
Percentile
39.8%
curl supports the Content-disposition
header, including the filename=
option. By design, curl does not allow server-provided local file override by verifying that the filename=
argument does not exist before opening it.
However, the implementation contains 2 minor logical bugs that allow a server to override an arbitrary local file (without path traversal) when running curl with specific command line args (-OJi)
This bug can trigger a logical RCE when curl is used from the user’s home dir (or other specific directories), by overriding specific files (e.g. “.bashrc”), while keeping the user completely uninformed of the side effects.
The 2 bugs are:
curl -iJ
is not supported however curl -Ji
is available -Content-disposition
handling flow does not allow opening existing files: https://github.com/curl/curl/blob/master/src/tool_cb_wrt.c#L54, however by using -OJi
it is possible to reach a flow that overrides a local file with the response headers, without verification: https://github.com/curl/curl/blob/master/src/tool_cb_hdr.c#L196HTTP/1.1 200 OK
<PAYLOAD>
Content-disposition: attachment; filename=".bashrc"
Where <PAYLOAD>
is the bash payload, e.g. echo pwn
curl -OJi
from the user’s home dirNote that curl falsely claims that .bashrc
was refused to be overwritten.
First bug:
case 'i':
config->show_headers = toggle; /* show the headers as well in the
general output stream */
break;
...
case 'J': /* --remote-header-name */
if(config->show_headers) {
warnf(global,
"--include and --remote-header-name cannot be combined.\n");
return PARAM_BAD_USE;
}
config->content_disposition = toggle;
break;
Second bug:
if(filename) {
if(outs->stream) {
int rc;
/* already opened and possibly written to */
if(outs->fopened)
fclose(outs->stream);
outs->stream = NULL;
/* rename the initial file name to the new file name */
rc = rename(outs->filename, filename);
if(rc != 0) {
warnf(per->config->global, "Failed to rename %s -> %s: %s\n",
outs->filename, filename, strerror(errno));
}
if(outs->alloc_filename)
Curl_safefree(outs->filename);
if(rc != 0) {
free(filename);
return failure;
}
}
Local file override without path traversal, possibly leading to an RCE or loss of data.
7.8 High
CVSS3
Attack Vector
LOCAL
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
4.6 Medium
CVSS2
Access Vector
LOCAL
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
PARTIAL
Availability Impact
PARTIAL
AV:L/AC:L/Au:N/C:P/I:P/A:P
0.001 Low
EPSS
Percentile
39.8%