From ad60af55e635bd93f81054b8ca42779d376105ac Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 12 Oct 2021 14:34:18 +0200 Subject: [PATCH 1/2] Fix #81518: Header injection via default_mimetype / default_charset We forbid setting these INI options to values containing NUL bytes, CR or LF. --- main/main.c | 19 ++++++++++++++++++- sapi/cgi/tests/bug81518a.phpt | 14 ++++++++++++++ sapi/cgi/tests/bug81518b.phpt | 11 +++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 sapi/cgi/tests/bug81518a.phpt create mode 100644 sapi/cgi/tests/bug81518b.phpt diff --git a/main/main.c b/main/main.c index 533417a569368..8f0ce5bf70b89 100644 --- a/main/main.c +++ b/main/main.c @@ -614,6 +614,10 @@ PHPAPI void (*php_internal_encoding_changed)(void) = NULL; */ static PHP_INI_MH(OnUpdateDefaultCharset) { + if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value)) + || strpbrk(ZSTR_VAL(new_value), "\r\n")) { + return FAILURE; + } OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); if (php_internal_encoding_changed) { php_internal_encoding_changed(); @@ -627,6 +631,19 @@ static PHP_INI_MH(OnUpdateDefaultCharset) } /* }}} */ +/* {{{ PHP_INI_MH + */ +static PHP_INI_MH(OnUpdateDefaultMimeTye) +{ + char *s = ZSTR_VAL(new_value), *e = s + ZSTR_LEN(new_value); + if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value)) + || strpbrk(ZSTR_VAL(new_value), "\r\n")) { + return FAILURE; + } + return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} +/* }}} */ + /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnUpdateInternalEncoding) @@ -782,7 +799,7 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("auto_prepend_file", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateString, auto_prepend_file, php_core_globals, core_globals) STD_PHP_INI_ENTRY("doc_root", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, doc_root, php_core_globals, core_globals) STD_PHP_INI_ENTRY("default_charset", PHP_DEFAULT_CHARSET, PHP_INI_ALL, OnUpdateDefaultCharset, default_charset, sapi_globals_struct, sapi_globals) - STD_PHP_INI_ENTRY("default_mimetype", SAPI_DEFAULT_MIMETYPE, PHP_INI_ALL, OnUpdateString, default_mimetype, sapi_globals_struct, sapi_globals) + STD_PHP_INI_ENTRY("default_mimetype", SAPI_DEFAULT_MIMETYPE, PHP_INI_ALL, OnUpdateDefaultMimeTye, default_mimetype, sapi_globals_struct, sapi_globals) STD_PHP_INI_ENTRY("internal_encoding", NULL, PHP_INI_ALL, OnUpdateInternalEncoding, internal_encoding, php_core_globals, core_globals) STD_PHP_INI_ENTRY("input_encoding", NULL, PHP_INI_ALL, OnUpdateInputEncoding, input_encoding, php_core_globals, core_globals) STD_PHP_INI_ENTRY("output_encoding", NULL, PHP_INI_ALL, OnUpdateOutputEncoding, output_encoding, php_core_globals, core_globals) diff --git a/sapi/cgi/tests/bug81518a.phpt b/sapi/cgi/tests/bug81518a.phpt new file mode 100644 index 0000000000000..8e48056df5e4d --- /dev/null +++ b/sapi/cgi/tests/bug81518a.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #81518 (Header injection via default_mimetype / default_charset) +--CGI-- +--FILE-- + +--EXPECTHEADERS-- +Content-type: text/html; charset=UTF-8 +--EXPECT-- diff --git a/sapi/cgi/tests/bug81518b.phpt b/sapi/cgi/tests/bug81518b.phpt new file mode 100644 index 0000000000000..75bbf7c8c08dc --- /dev/null +++ b/sapi/cgi/tests/bug81518b.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #81518 (Header injection via default_mimetype / default_charset) +--CGI-- +--FILE-- + +--EXPECTHEADERS-- +Content-type: text/html;charset=UTF-8 +--EXPECT-- From 9d5f0aa17de2148cd0d3d4e78dcb2042275ee57b Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 12 Oct 2021 15:34:25 +0200 Subject: [PATCH 2/2] Remove leftovers from previous solution attempt --- main/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/main/main.c b/main/main.c index 8f0ce5bf70b89..0b33b2b56c9a9 100644 --- a/main/main.c +++ b/main/main.c @@ -635,7 +635,6 @@ static PHP_INI_MH(OnUpdateDefaultCharset) */ static PHP_INI_MH(OnUpdateDefaultMimeTye) { - char *s = ZSTR_VAL(new_value), *e = s + ZSTR_LEN(new_value); if (memchr(ZSTR_VAL(new_value), '\0', ZSTR_LEN(new_value)) || strpbrk(ZSTR_VAL(new_value), "\r\n")) { return FAILURE;