Hi, I prepared a patch to check the Set-Cookie domain values for being Public Suffices using libpsl. This is mainly for detecting and preventing 'Supercookies' being set by 'bad' web servers.
Here are some references for more detailed information: https://publicsuffix.org/ https://github.com/publicsuffix/list https://github.com/rockdaboot/libpsl The patch is missing a test case - it was not obvious for me how to prevent such a test being performed when libpsl is not compiled in. I added 'has_psl' to test/runtests.pl but here I am stuck. If you could give me a hint on that (please with a test number), I'll make up a test case. On Debian, Fedora, Arch and maybe some other distros libpsl has already been packaged (Debian: libpsl-dev, libpsl0:amd64, libpsl0-dbg:amd64, psl). Please review / test the patch. Regards, Tim
>From ee2fc8d2f571c620f4c97e575c00b98e289a611d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20R=C3=BChsen?= <[email protected]> Date: Tue, 29 Sep 2015 11:33:01 +0200 Subject: [PATCH] Add support for Mozilla's Publix Suffix List Use libpsl to check the domain value of Set-Cookie headers (and cookie jar entries) for not being a Publix Suffix. Ref: https://publicsuffix.org/ Ref: https://github.com/publicsuffix/list Ref: https://github.com/rockdaboot/libpsl --- configure.ac | 14 ++++++++++++++ lib/cookie.c | 21 +++++++++++++++++++++ lib/version.c | 9 +++++++++ src/tool_help.c | 3 +++ tests/runtests.pl | 18 +++++++++++++++++- 5 files changed, 64 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 26d77eb..771deac 100644 --- a/configure.ac +++ b/configure.ac @@ -166,6 +166,7 @@ curl_verbose_msg="enabled (--disable-verbose)" curl_rtsp_msg="no (--enable-rtsp)" curl_rtmp_msg="no (--with-librtmp)" curl_mtlnk_msg="no (--with-libmetalink)" + curl_psl_msg="no (--with-libpsl)" init_ssl_msg=${curl_ssl_msg} @@ -2314,6 +2315,18 @@ dnl ********************************************************************** CURL_CHECK_CA_BUNDLE dnl ********************************************************************** +dnl Check for libpsl +dnl ********************************************************************** + +AC_ARG_WITH(libpsl, AS_HELP_STRING([--without-libpsl], [disable support for libpsl cookie checking]), with_libpsl=$withval, with_libpsl=yes) +if test $with_libpsl != "no"; then + AC_SEARCH_LIBS(psl_builtin, psl, + [curl_psl_msg="yes"; AC_DEFINE([USE_LIBPSL], [1], [PSL support enabled])], + [curl_psl_msg="no (libpsl not found)"; AC_MSG_WARN(*** libpsl was not found. Supercookie vulnerability possible.)]) +fi +AM_CONDITIONAL([USE_LIBPSL], [test "$curl_psl_msg" = "yes"]) + +dnl ********************************************************************** dnl Check for libmetalink dnl ********************************************************************** @@ -3741,6 +3754,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: RTSP support: ${curl_rtsp_msg} RTMP support: ${curl_rtmp_msg} metalink support: ${curl_mtlnk_msg} + PSL support: ${curl_psl_msg} HTTP2 support: ${curl_h2_msg} Protocols: ${SUPPORT_PROTOCOLS} ]) diff --git a/lib/cookie.c b/lib/cookie.c index 22730cf..e09cea1 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -84,6 +84,10 @@ Example set of cookies: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) +#ifdef USE_LIBPSL +# include <libpsl.h> +#endif + #include "curl_printf.h" #include "urldata.h" #include "cookie.h" @@ -379,6 +383,10 @@ Curl_cookie_add(struct SessionHandle *data, bool replace_old = FALSE; bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */ +#ifdef USE_LIBPSL + const psl_ctx_t *psl; +#endif + #ifdef CURL_DISABLE_VERBOSE_STRINGS (void)data; #endif @@ -777,6 +785,19 @@ Curl_cookie_add(struct SessionHandle *data, /* at first, remove expired cookies */ remove_expired(c); +#ifdef USE_LIBPSL + /* Check if the domain is a Public Suffix and if yes, ignore the cookie. + This needs a libpsl compiled with builtin data. */ + if(co->domain && !isip(co->domain) && (psl = psl_builtin()) != NULL) { + if(psl_is_public_suffix(psl, co->domain)) { + /* infof("cookie '%s' dropped, domain '%s' is a public suffix\n", co->name, co->domain); */ + fprintf(stderr,"cookie '%s' dropped, domain '%s' is a public suffix\n", co->name, co->domain); + freecookie(co); + return NULL; + } + } +#endif + clist = c->cookies; replace_old = FALSE; while(clist) { diff --git a/lib/version.c b/lib/version.c index 1727c5a..8784c2b 100644 --- a/lib/version.c +++ b/lib/version.c @@ -40,6 +40,10 @@ #include <stringprep.h> #endif +#ifdef USE_LIBPSL +#include <libpsl.h> +#endif + #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) #include <iconv.h> #endif @@ -100,6 +104,11 @@ char *curl_version(void) ptr += len; } #endif +#ifdef USE_LIBPSL + len = snprintf(ptr, left, " libpsl/%s", psl_get_version()); + left -= len; + ptr += len; +#endif #ifdef USE_WIN32_IDN len = snprintf(ptr, left, " WinIDN"); left -= len; diff --git a/src/tool_help.c b/src/tool_help.c index 355fe7d..4f569cd 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -317,6 +317,9 @@ void tool_version_info(void) #ifdef USE_METALINK printf("Metalink "); #endif +#ifdef USE_LIBPSL + printf("PSL "); +#endif puts(""); /* newline */ } } diff --git a/tests/runtests.pl b/tests/runtests.pl index 377d733..6e9f4a1 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -224,6 +224,7 @@ my $has_http2; # set if libcurl is built with HTTP2 support my $has_crypto; # set if libcurl is built with cryptographic support my $has_cares; # set if built with c-ares my $has_threadedres;# set if built with threaded resolver +my $has_psl; # set if libcurl is built with PSL support # this version is decided by the particular nghttp2 library that is being used my $h2cver = "h2c"; @@ -2474,6 +2475,10 @@ sub checksystem { # Metalink enabled $has_metalink=1; } + if($feat =~ /PSL/i) { + # PSL enabled + $has_psl=1; + } if($feat =~ /AsynchDNS/i) { if(!$has_cares) { # this means threaded resolver @@ -2599,8 +2604,9 @@ sub checksystem { logmsg sprintf("* HTTP Unix %s\n", $http_unix?"ON ":"OFF"); logmsg sprintf("* FTP IPv6 %8s", $ftp_ipv6?"ON ":"OFF"); logmsg sprintf(" Libtool lib: %s\n", $libtool?"ON ":"OFF"); - logmsg sprintf("* Shared build: %-3s", $has_shared); + logmsg sprintf("* PSL: %8s", $has_psl?"ON ":"OFF"); logmsg sprintf(" Resolver: %s\n", $resolver); + if($ssl_version) { logmsg sprintf("* SSL library: %13s\n", $ssllib); } @@ -2981,6 +2987,11 @@ sub singletest { next; } } + elsif($1 eq "PSL") { + if($has_psl) { + next; + } + } elsif($1 eq "socks") { next; } @@ -3117,6 +3128,11 @@ sub singletest { next; } } + elsif($1 eq "PSL") { + if(!$has_psl) { + next; + } + } else { next; } -- 2.5.3
------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html
