[SECURITY ADVISORY] remote file name path traversal in curl tool for Windows
Daniel Stenberg <daniel <at> haxx.se>
2016-01-27 07:46:09 GMT
remote file name path traversal in curl tool for Windows
Project cURL Security Advisory, January 27th 2016 -
curl does not sanitize colons in a remote file name that is used as the local
file name. This may lead to a vulnerability on systems where the colon is a
special path character. Currently Windows is the only OS where this
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 file name for the content,
curl will write its output to that server-provided file name, as long as that
file does not already exist. If it does exist curl will fail to write.
If both options are used together (-OJ) but the server does not provide a
remote file name, or if -O is used without -J, curl will write output to a
file name based solely on the remote file name 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 file name. 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 (ie outside the
current working directory), and also possible to write to a file's alternate
For example if curl -OJ and the server sends filename=f:foo curl will
incorrectly write foo to the working directory for drive F even if drive F
isn't the current drive. For a more detailed explanation see the 'MORE
BACKGROUND AND EXAMPLE' section at the end of this notice.
Though no known exploit is available for this issue, writing one would be
undemanding and could be serious depending on the name of the file and where
it ends up being written.
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.
In the case of using a remote file name provided by the user (-O without -J),
the feature has existed since inception. <- check this I'm not sure.
- Affected versions (-O): curl <= 7.46.0
- Not affected versions (-O): curl >= 7.47.0
In the case of using a remote file name provided by the server (-OJ), the
feature was added in 7.20.0 and didn't exist before then.
- Affected versions (-OJ): curl 7.20.0 to and including 7.46.0
- Not affected versions (-OJ): curl < 7.20.0 and curl >= 7.47.0
Starting in curl 7.47.0 the curl tool in Windows will replace all colons in a
remote file name with underscores. For example if f:foo::$DATA is the remote
file name it will be sanitized as f_foo__$DATA .
A patch is available at:
Exercise judicious use of the -J option. The -J option when combined with -O
lets the server choose the file name. 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 will still be
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
We suggest you take one of the following actions immediately, in order of
A - Upgrade curl and libcurl to version 7.47.0.
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
Regardless of which action you take, exercise judicious use of the -J option as
described in THE SOLUTION.
It was first reported to the curl project on November 30 2015. We contacted
distros <at> openwall on January 21 2016.
curl 7.47.0 was released on January 27 2016, coordinated with the publication
of this advisory.
Reported and 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
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 will
be 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 will strip the path to get the file name 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
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 file name is parsed from the
server's "Content-Disposition:" header if one is given (eg
`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
List admin: http://cool.haxx.se/list/listinfo/curl-users