From: 1seal Date: Mon, 9 Mar 2026 10:48:49 +0000 (+0100) Subject: Fix OSSL_parse_url userinfo scan past authority X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7aedbb34d01cc3dca6218bad454d795c09ba89e7;p=thirdparty%2Fopenssl.git Fix OSSL_parse_url userinfo scan past authority Reviewed-by: Paul Dale Reviewed-by: Norbert Pocs MergeDate: Wed Mar 11 10:22:54 2026 (Merged from https://github.com/openssl/openssl/pull/30319) --- diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c index 54c5c6ec1d8..2821c0ec528 100644 --- a/crypto/http/http_lib.c +++ b/crypto/http/http_lib.c @@ -55,6 +55,7 @@ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, char **ppath, char **pquery, char **pfrag) { const char *p, *tmp; + const char *authority_end; const char *scheme, *scheme_end; const char *user, *user_end; const char *host, *host_end; @@ -92,7 +93,10 @@ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, /* parse optional "userinfo@" */ user = user_end = host = p; - host = strchr(p, '@'); + authority_end = strpbrk(p, "/?#"); + if (authority_end == NULL) + authority_end = p + strlen(p); + host = memchr(p, '@', authority_end - p); if (host != NULL) user_end = host++; else diff --git a/test/http_test.c b/test/http_test.c index e7a402dae61..c7e4630d93f 100644 --- a/test/http_test.c +++ b/test/http_test.c @@ -331,6 +331,18 @@ static int test_http_url_path_query_ok(const char *url, const char *exp_path_qu) return res; } +static int test_http_url_host_ok(const char *url, const char *exp_host) +{ + char *host; + int res; + + res = TEST_true(OSSL_HTTP_parse_url(url, NULL, NULL, &host, NULL, NULL, + NULL, NULL, NULL)) + && TEST_str_eq(host, exp_host); + OPENSSL_free(host); + return res; +} + static int test_http_url_dns(void) { return test_http_url_ok("host:65535/path", 0, "host", "65535", "/path"); @@ -358,6 +370,13 @@ static int test_http_url_userinfo_query_fragment(void) return test_http_url_ok("user:pass@host/p?q#fr", 0, "host", "80", "/p"); } +static int test_http_url_at_sign_outside_authority(void) +{ + return test_http_url_host_ok("http://host/p@attacker.test", "host") + && test_http_url_host_ok("http://host/p?q=@attacker.test", "host") + && test_http_url_host_ok("http://host/p?q#fr@attacker.test", "host"); +} + static int test_http_url_ipv4(void) { return test_http_url_ok("https://1.2.3.4/p/q", 1, "1.2.3.4", "443", "/p/q"); @@ -576,6 +595,7 @@ int setup_tests(void) ADD_TEST(test_http_url_timestamp); ADD_TEST(test_http_url_path_query); ADD_TEST(test_http_url_userinfo_query_fragment); + ADD_TEST(test_http_url_at_sign_outside_authority); ADD_TEST(test_http_url_ipv4); ADD_TEST(test_http_url_ipv6); ADD_TEST(test_http_url_invalid_prefix);