From 4a89e726bd4d0571991dc22a9a1ad4509e8fe347 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 19 Jan 2021 11:23:25 +0100 Subject: Alternative fix for bug 77423 That bug report originally was about `parse_url()` misbehaving, but the security aspect was actually only regarding `FILTER_VALIDATE_URL`. Since the changes to `parse_url_ex()` apparently affect userland code which is relying on the sloppy URL parsing[1], this alternative restores the old parsing behavior, but ensures that the userinfo is checked for correctness for `FILTER_VALIDATE_URL`. [1] --- ext/filter/logical_filters.c | 23 +++++++++++++++++++++++ ext/filter/tests/bug77423.phpt | 15 +++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 ext/filter/tests/bug77423.phpt (limited to 'ext/filter') diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 076d247946..1cf345dbb5 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -532,6 +532,22 @@ void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } /* }}} */ +static int is_userinfo_valid(zend_string *str) +{ + const char *valid = "-._~!$&'()*+,;=:"; + const char *p = ZSTR_VAL(str); + while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) { + if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) { + p++; + } else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) { + p += 3; + } else { + return 0; + } + } + return 1; +} + void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { php_url *url; @@ -592,6 +608,13 @@ bad_url: php_url_free(url); RETURN_VALIDATION_FAILED } + + if (url->user != NULL && !is_userinfo_valid(url->user)) { + php_url_free(url); + RETURN_VALIDATION_FAILED + + } + php_url_free(url); } /* }}} */ diff --git a/ext/filter/tests/bug77423.phpt b/ext/filter/tests/bug77423.phpt new file mode 100644 index 0000000000..761c7c359a --- /dev/null +++ b/ext/filter/tests/bug77423.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #77423 (parse_url() will deliver a wrong host to user) +--FILE-- + +--EXPECT-- +bool(false) +bool(false) -- cgit v1.2.1