CVE-2016-0754
remote filename path traversal in curl tool for Windows
Project curl Security Advisory, January 27th 2016 - Permalink
VULNERABILITY
curl does not sanitize colons in a remote filename that is used as the local filename. This may lead to a vulnerability on systems where the colon is a special path character. Currently Windows is the only OS where this vulnerability applies.
curl offers command line options --remote-name (also usable as
-O
) and --remote-header-name
(also usable as
-J
). When both of those options are used together (-OJ) and
the server provides a remote filename for the content, curl writes its
output to that server-provided filename, as long as that file does not
already exist. If it does exist curl fails to write.
If both options are used together (-OJ
) but the server
does not provide a remote filename, or if -O
is used
without -J
, curl writes output to a filename based solely
on the remote filename in the URL string provided by the user,
regardless of whether or not that file already exists.
In either case curl does not sanitize colons in the filename. As a result in Windows it is possible and unintended behavior for curl to write to a file in the working directory of a drive that is not the current drive (i.e. outside the current working directory), and also possible to write to a file's alternate data stream.
For example if curl -OJ
and the server sends
filename=f:foo curl incorrectly writes foo to the working directory for
drive F even if drive F is not the current drive. For a more detailed
explanation see the 'MORE BACKGROUND AND EXAMPLE' section towards the
end of this advisory.
Though no known exploit is available for this issue at the time of the publication, writing one would be undemanding and could be serious depending on the name of the file and where it ends up being written.
INFO
This flaw only affects the curl command line tool as this is a feature not present or provided by libcurl.
The Common Vulnerabilities and Exposures (CVE) project has assigned the name CVE-2016-0754 to this issue.
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Severity: High
AFFECTED VERSIONS
In the case of using a remote filename provided by the user
(-O
without -J
), the feature has existed since
inception.
In the case of using a remote filename provided by the server
(-OJ
), the feature was added in 7.20.0 and did not exist
before then.
curl built for Cygwin is partially affected (-O
): curl
<= 7.47.0. Please refer to the CYGWIN addendum at the end of this
advisory. (Added 2016-02-07)
SOLUTION
Starting in curl 7.47.0 the curl tool in Windows replaces all colons
in a remote filename with underscores. For example if
f:foo::$DATA
is the remote filename, it is sanitized to
f_foo__$DATA
.
Exercise judicious use of the -J
option. The
-J
option when combined with -O
lets the
server choose the filename. Do you trust the server you are using the
-J
option on? Is your connection to the server vulnerable
to a man-in-the-middle attack? Have you enabled location redirects and
the server may send you somewhere untrustworthy? In any of these cases,
even with this vulnerability fixed know that if you use the
-J
option it still is possible for a rogue server to send
you the name of a DLL or other file that could possibly be loaded
automatically by Windows or some third party software.
RECOMMENDATIONS
We suggest you take one of the following actions immediately, in order of preference:
A - Upgrade curl and libcurl to version 7.47.1.
B - Apply the patch to your version and rebuild.
C - If you cannot do (A) or (B) it is suggested you do not use
-J
on Windows. If you choose to continue to use
-O
without -J
it is your responsibility to
check that the URL you pass does not have a remote file name that could
be exploited.
Regardless of which action you take, exercise judicious use of the
-J
option as described in THE SOLUTION.
TIMELINE
It was first reported to the curl project on November 30 2015. We contacted distros@openwall on January 21 2016.
curl 7.47.0 was released on January 27 2016, coordinated with the publication of this advisory.
curl 7.47.1 was released the week of February 8, 2016 to address
over-sanitation of an --output
path caused by the first
revision of the patch for this issue; and additionally to not allow curl
built for Cygwin to write outside the current working directory when a
backslash is in the remote filename (-O
).
CREDITS
- Reported-by: Ray Satiro (Jay)
- Patched-by: Ray Satiro (Jay)
Thanks a lot!
MORE BACKGROUND AND EXAMPLE
In Windows if a colon is used to specify a drive letter for a path and there is a slash or backslash (hereafter path separator) that proceeds the colon it means start from the root of the drive, but if that slash is omitted it means start from the current working directory of the drive.
C:\foo
=> Windows looks for foo in the root directory of drive C.C:foo
=> Windows looks for foo in the working directory of drive C.
A process in Windows on its creation may inherit a list of drives and their working directories from its parent, and one of those is the current working directory.
For example a command prompt is open and has these working directories:
- Drive C, Path
\bar\baz\
- Drive D, Path
\
- Drive E, Path
\qux\
<-- Current - Drive F, Path
\
Assume other drives were not accessed which means they default to their root.
A user running curl from that command prompt would expect that their
file is output to the current working directory, E:\qux\
in
this example. However that may not happen if there is a colon in the
filename.
curl has a function which strips the path to get the filename by removing the last path separator and everything that precedes it. In the case of a colon without a path separator that comes after it, it is not removed from the file name.
Following this example:
In the case of -O
without -J
recall that
the filename is parsed from the user- supplied URL, and is written
regardless of whether the file already exists.
curl -O http://somewhere/f:foo
=> curl writes output
to f:\foo
curl -O http://somewhere/c:foo
=> curl writes output
to c:\bar\baz\foo
In the case of -O
with -J
recall that the
filename is parsed from the server's "Content-Disposition:" header if
one is given (for example
Content-Disposition: attachment; filename=abc
) and in that
case the file is written only if it does not already exist.
curl -OJ http://somewhere/somefile
=> Server sends
filename=f:foo
curl writes output to
f:\foo
curl -OJ http://somewhere/somefile
=> Server sends
filename=c:foo
curl writes output to
c:\bar\baz\foo
CYGWIN
(Added 2016-02-07) Since the original publishing of this advisory it has been determined that curl built for Cygwin is partially vulnerable.
By default Cygwin sanitizes colons and other banned filename characters by replacing them with Unicode characters. However Cygwin does not do this for the backslash and in such a case may not map a colon that precedes a backslash to a Unicode character. In curl <= 7.47.0 built for Cygwin it is possible to write outside the current working directory by specifying a remote filename with backslashes.
For example:
curl -O 'http://example.com/F:\foo'
saves to F:\foo.
curl built for Cygwin is not vulnerable to an (-OJ
)
rogue server attack, therefore the scope of this vulnerability as it
applies to Cygwin is limited to unchecked user input, such as if you
have a script that is passing an untrusted URL to curl built for
Cygwin.
curl 7.47.1 checks for backslashes for all operating systems: A remote file name is parsed from the URL by removing anything up to and including the last forward slash or back slash of the URL's path segment.