Skip to content

Commit

Permalink
- David Kierznowski notified us about a security flaw
Browse files Browse the repository at this point in the history
  (http://curl.haxx.se/docs/adv_20090303.html also known as CVE-2009-0037) in
  which previous libcurl versions (by design) can be tricked to access an
  arbitrary local/different file instead of a remote one when
  CURLOPT_FOLLOWLOCATION is enabled. This flaw is now fixed in this release
  together this the addition of two new setopt options for controlling this
  new behavior:

  o CURLOPT_REDIR_PROTOCOLS controls what protocols libcurl is allowed to
  follow to when CURLOPT_FOLLOWLOCATION is enabled. By default, this option
  excludes the FILE and SCP protocols and thus you nee to explicitly allow
  them in your app if you really want that behavior.

  o CURLOPT_PROTOCOLS controls what protocol(s) libcurl is allowed to fetch
  using the primary URL option. This is useful if you want to allow a user or
  other outsiders control what URL to pass to libcurl and yet not allow all
  protocols libcurl may have been built to support.
  • Loading branch information
bagder committed Mar 2, 2009
1 parent 90b804d commit 042cc1f
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 16 deletions.
21 changes: 21 additions & 0 deletions CHANGES
Expand Up @@ -6,6 +6,27 @@

Changelog

Version 7.19.4 (3 March 2009)

Daniel Stenberg (3 Mar 2009)
- David Kierznowski notified us about a security flaw
(http://curl.haxx.se/docs/adv_20090303.html also known as CVE-2009-0037) in
which previous libcurl versions (by design) can be tricked to access an
arbitrary local/different file instead of a remote one when
CURLOPT_FOLLOWLOCATION is enabled. This flaw is now fixed in this release
together this the addition of two new setopt options for controlling this
new behavior:

o CURLOPT_REDIR_PROTOCOLS controls what protocols libcurl is allowed to
follow to when CURLOPT_FOLLOWLOCATION is enabled. By default, this option
excludes the FILE and SCP protocols and thus you nee to explicitly allow
them in your app if you really want that behavior.

o CURLOPT_PROTOCOLS controls what protocol(s) libcurl is allowed to fetch
using the primary URL option. This is useful if you want to allow a user or
other outsiders control what URL to pass to libcurl and yet not allow all
protocols libcurl may have been built to support.

Daniel Stenberg (27 Feb 2009)
- Senthil Raja Velu reported a problem when CURLOPT_INTERFACE and
CURLOPT_LOCALPORT were used together (the local port bind failed), and
Expand Down
10 changes: 8 additions & 2 deletions RELEASE-NOTES
Expand Up @@ -2,11 +2,16 @@ Curl and libcurl 7.19.4

Public curl releases: 110
Command line options: 132
curl_easy_setopt() options: 161
curl_easy_setopt() options: 163
Public functions in libcurl: 58
Known libcurl bindings: 38
Contributors: 700

This release includes the following security-related fix:

o CVE-2009-0037 with the curl advisory here:
http://curl.haxx.se/docs/adv_20090303.html

This release includes the following changes:

o Added CURLOPT_NOPROXY and the corresponding --noproxy
Expand All @@ -24,6 +29,7 @@ This release includes the following changes:
o CURLOPT_FTP_CREATE_MISSING_DIRS can now be set to 2 to retry the CWD even
when MKD fails
o GnuTLS initing moved to curl_global_init()
o Added CURLOPT_REDIR_PROTOCOLS and CURLOPT_PROTOCOLS

This release includes the following bugfixes:

Expand Down Expand Up @@ -59,6 +65,6 @@ advice from friends like these:
Patrick Scott, Hidemoto Nakada, Jocelyn Jaubert, Andre Guibert de Bruet,
Kamil Dudka, Patrik Thunstrom, Linus Nielsen Feltzing, Mark Incley,
Daniel Johnson, James Cheng, Brian J. Murrell, Senthil Raja Velu,
Markus Koetter
Markus Koetter, David Kierznowski, Michal Marek

Thanks! (and sorry if I forgot to mention someone)
24 changes: 24 additions & 0 deletions docs/libcurl/curl_easy_setopt.3
Expand Up @@ -440,6 +440,26 @@ The string given to CURLOPT_URL must be url-encoded and follow RFC 2396

\fICURLOPT_URL\fP is the only option that \fBmust\fP be set before
\fIcurl_easy_perform(3)\fP is called.

\fICURLOPT_PROTOCOLS\fP can be used to limit what protocols libcurl will use
for this transfer, independent of what libcurl has been compiled to
support. That may be useful if you accept the URL from an external source and
want to limit the accessibility.
.IP CURLOPT_PROTOCOLS
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in the transfer. This allows you to have
a libcurl built to support a wide range of protocols but still limit specific
transfers to only be allowed to use a subset of them. By default libcurl will
accept all protocols it supports. See also
\fICURLOPT_REDIR_PROTOCOLS\fP. (Added in 7.19.4)
.IP CURLOPT_REDIR_PROTOCOLS
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
limits what protocols libcurl may use in a transfer that it follows to in a
redirect when \fICURLOPT_FOLLOWLOCATION\fP is enabled. This allows you to
limit specific transfers to only be allowed to use a subset of protocols in
redirections. By default libcurl will allow all protocols except for FILE and
SCP. This is a difference compared to pre-7.19.4 versions which
unconditionally would follow to all protocols supported. (Added in 7.19.4)
.IP CURLOPT_PROXY
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
string holding the host name or dotted IP address. To specify port number in
Expand Down Expand Up @@ -743,6 +763,10 @@ This means that the library will re-send the same request on the new location
and follow new Location: headers all the way until no more such headers are
returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
libcurl will follow.

NOTE: since 7.19.4, libcurl can limit to what protocols it will automatically
follow. The accepted protocols are set with \fICURLOPT_REDIR_PROTOCOLS\fP and
it excludes the FILE protocol by default.
.IP CURLOPT_UNRESTRICTED_AUTH
A parameter set to 1 tells the library it can continue to send authentication
(user+password) when following locations, even when hostname changed. This
Expand Down
15 changes: 15 additions & 0 deletions docs/libcurl/symbols-in-versions
Expand Up @@ -191,6 +191,7 @@ CURLOPT_PRIVATE 7.10.3
CURLOPT_PROGRESSDATA 7.1
CURLOPT_PROGRESSFUNCTION 7.1
CURLOPT_PROGRESSMODE 7.1 - 7.9.2
CURLOPT_PROTOCOLS 7.19.4
CURLOPT_PROXY 7.1
CURLOPT_PROXYAUTH 7.10.7
CURLOPT_PROXYPASSWORD 7.19.1
Expand All @@ -205,6 +206,7 @@ CURLOPT_RANDOM_FILE 7.7
CURLOPT_RANGE 7.1
CURLOPT_READDATA 7.9.7
CURLOPT_READFUNCTION 7.1
CURLOPT_REDIR_PROTOCOLS 7.19.4
CURLOPT_REFERER 7.1
CURLOPT_RESUME_FROM 7.1
CURLOPT_RESUME_FROM_LARGE 7.11.0
Expand Down Expand Up @@ -261,6 +263,19 @@ CURLOPT_VERBOSE 7.1
CURLOPT_WRITEDATA 7.9.7
CURLOPT_WRITEFUNCTION 7.1
CURLOPT_WRITEHEADER 7.1
CURLPROTO_ALL 7.19.4
CURLPROTO_DICT 7.19.4
CURLPROTO_FILE 7.19.4
CURLPROTO_FTP 7.19.4
CURLPROTO_FTPS 7.19.4
CURLPROTO_HTTP 7.19.4
CURLPROTO_HTTPS 7.19.4
CURLPROTO_LDAP 7.19.4
CURLPROTO_LDAPS 7.19.4
CURLPROTO_SCP 7.19.4
CURLPROTO_SFTP 7.19.4
CURLPROTO_TELNET 7.19.4
CURLPROTO_TFTP 7.19.4
CURLPROXY_HTTP 7.10
CURLPROXY_HTTP_1_0 7.19.4
CURLPROXY_SOCKS4 7.10
Expand Down
27 changes: 27 additions & 0 deletions include/curl/curl.h
Expand Up @@ -550,6 +550,21 @@ typedef enum {
CURLFTPMETHOD_LAST /* not an option, never use */
} curl_ftpmethod;

/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
#define CURLPROTO_HTTP (1<<0)
#define CURLPROTO_HTTPS (1<<1)
#define CURLPROTO_FTP (1<<2)
#define CURLPROTO_FTPS (1<<3)
#define CURLPROTO_SCP (1<<4)
#define CURLPROTO_SFTP (1<<5)
#define CURLPROTO_TELNET (1<<6)
#define CURLPROTO_LDAP (1<<7)
#define CURLPROTO_LDAPS (1<<8)
#define CURLPROTO_DICT (1<<9)
#define CURLPROTO_FILE (1<<10)
#define CURLPROTO_TFTP (1<<11)
#define CURLPROTO_ALL (~0) /* enable everything */

/* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */
#define CURLOPTTYPE_LONG 0
Expand Down Expand Up @@ -1185,6 +1200,18 @@ typedef enum {
/* Socks Service */
CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),

/* set the bitmask for the protocols that are allowed to be used for the
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
CINIT(PROTOCOLS, LONG, 181),

/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. Defaults
to all protocols except FILE and SCP. */
CINIT(REDIR_PROTOCOLS, LONG, 182),

CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

Expand Down
36 changes: 35 additions & 1 deletion lib/url.c
Expand Up @@ -683,6 +683,12 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */

/* for the *protocols fields we don't use the CURLPROTO_ALL convenience
define since we internally only use the lower 16 bits for the passed
in bitmask to not conflict with the private bits */
set->allowed_protocols = PROT_EXTMASK;
set->redir_protocols =
PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */

#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
Expand Down Expand Up @@ -2217,6 +2223,22 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.scope = (unsigned int) va_arg(param, long);
break;

case CURLOPT_PROTOCOLS:
/* set the bitmask for the protocols that are allowed to be used for the
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
data->set.allowed_protocols = va_arg(param, long) & PROT_EXTMASK;
break;

case CURLOPT_REDIR_PROTOCOLS:
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. Defaults
to all protocols except FILE and SCP. */
data->set.redir_protocols = va_arg(param, long) & PROT_EXTMASK;
break;

default:
/* unknown tag and its companion, just ignore: */
result = CURLE_FAILED_INIT; /* correct this */
Expand Down Expand Up @@ -3371,7 +3393,19 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,

for (pp = protocols; (p = *pp) != NULL; pp++)
if(Curl_raw_equal(p->scheme, conn->protostr)) {
/* Protocol found in table. Perform setup complement if some. */
/* Protocol found in table. Check if allowed */
if(!(data->set.allowed_protocols & p->protocol))
/* nope, get out */
break;

/* it is allowed for "normal" request, now do an extra check if this is
the result of a redirect */
if(data->state.this_is_a_follow &&
!(data->set.redir_protocols & p->protocol))
/* nope, get out */
break;

/* Perform setup complement if some. */
conn->handler = p;

if(p->setup_connection) {
Expand Down
35 changes: 22 additions & 13 deletions lib/urldata.h
Expand Up @@ -891,19 +891,26 @@ struct connectdata {
long connectindex; /* what index in the connection cache connects index this
particular struct has */
long protocol; /* PROT_* flags concerning the protocol set */
#define PROT_MISSING (1<<0)
#define PROT_HTTP (1<<2)
#define PROT_HTTPS (1<<3)
#define PROT_FTP (1<<4)
#define PROT_TELNET (1<<5)
#define PROT_DICT (1<<6)
#define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8)
#define PROT_FTPS (1<<9)
#define PROT_SSL (1<<10) /* protocol requires SSL */
#define PROT_TFTP (1<<11)
#define PROT_SCP (1<<12)
#define PROT_SFTP (1<<13)
#define PROT_HTTP CURLPROTO_HTTP
#define PROT_HTTPS CURLPROTO_HTTPS
#define PROT_FTP CURLPROTO_FTP
#define PROT_TELNET CURLPROTO_TELNET
#define PROT_DICT CURLPROTO_DICT
#define PROT_LDAP CURLPROTO_LDAP
#define PROT_FILE CURLPROTO_FILE
#define PROT_FTPS CURLPROTO_FTPS
#define PROT_TFTP CURLPROTO_TFTP
#define PROT_SCP CURLPROTO_SCP
#define PROT_SFTP CURLPROTO_SFTP

/* CURLPROTO_TFTP (1<<11) is currently the highest used bit in the public
bitmask. We make sure we use "private bits" above the first 16 to make
things easier. */

#define PROT_EXTMASK 0xffff

#define PROT_SSL (1<<22) /* protocol requires SSL */
#define PROT_MISSING (1<<23)

#define PROT_CLOSEACTION PROT_FTP /* these ones need action before socket
close */
Expand Down Expand Up @@ -1533,6 +1540,8 @@ struct UserDefined {
via an HTTP proxy */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
unsigned int scope; /* address scope for IPv6 */
long allowed_protocols;
long redir_protocols;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
long socks5_gssapi_nec; /* flag to support nec socks5 server */
#endif
Expand Down

0 comments on commit 042cc1f

Please sign in to comment.