summaryrefslogtreecommitdiffstats
path: root/php-cve-2024-8926.patch
diff options
context:
space:
mode:
Diffstat (limited to 'php-cve-2024-8926.patch')
-rw-r--r--php-cve-2024-8926.patch230
1 files changed, 230 insertions, 0 deletions
diff --git a/php-cve-2024-8926.patch b/php-cve-2024-8926.patch
new file mode 100644
index 0000000..679ad7b
--- /dev/null
+++ b/php-cve-2024-8926.patch
@@ -0,0 +1,230 @@
+From 0bd3bd616f6139dd1e076bb2e0df1a74ef298c76 Mon Sep 17 00:00:00 2001
+From: Jan Ehrhardt <github@ehrhardt.nl>
+Date: Wed, 5 Jun 2024 20:42:45 +0200
+Subject: [PATCH 1/9] Fix GHSA-3qgc-jrrr-25jv
+
+---
+ sapi/cgi/cgi_main.c | 23 ++++++++++++++-
+ sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt | 38 +++++++++++++++++++++++++
+ 2 files changed, 60 insertions(+), 1 deletion(-)
+ create mode 100644 sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt
+
+diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
+index a735056e9a..1996eb6e87 100644
+--- a/sapi/cgi/cgi_main.c
++++ b/sapi/cgi/cgi_main.c
+@@ -1830,8 +1830,13 @@ int main(int argc, char *argv[])
+ }
+ }
+
++ /* Apache CGI will pass the query string to the command line if it doesn't contain a '='.
++ * This can create an issue where a malicious request can pass command line arguments to
++ * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode,
++ * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`.
++ * Therefore, this code only prevents passing arguments if the query string starts with a '-'.
++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */
+ if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
+- /* we've got query string that has no = - apache CGI will pass it to command line */
+ unsigned char *p;
+ decoded_query_string = strdup(query_string);
+ php_url_decode(decoded_query_string, strlen(decoded_query_string));
+@@ -1841,6 +1846,22 @@ int main(int argc, char *argv[])
+ if(*p == '-') {
+ skip_getopt = 1;
+ }
++
++ /* On Windows we have to take into account the "best fit" mapping behaviour. */
++#ifdef PHP_WIN32
++ if (*p >= 0x80) {
++ wchar_t wide_buf[1];
++ wide_buf[0] = *p;
++ char char_buf[4];
++ size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
++ size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
++ if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0
++ || char_buf[0] == '-') {
++ skip_getopt = 1;
++ }
++ }
++#endif
++
+ free(decoded_query_string);
+ }
+
+diff --git a/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt
+new file mode 100644
+index 0000000000..fd2fcdfbf8
+--- /dev/null
++++ b/sapi/cgi/tests/ghsa-3qgc-jrrr-25jv.phpt
+@@ -0,0 +1,38 @@
++--TEST--
++GHSA-3qgc-jrrr-25jv
++--SKIPIF--
++<?php
++include 'skipif.inc';
++if (PHP_OS_FAMILY !== "Windows") die("skip Only for Windows");
++
++$codepage = trim(shell_exec("powershell Get-ItemPropertyValue HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage ACP"));
++if ($codepage !== '932' && $codepage !== '936' && $codepage !== '950') die("skip Wrong codepage");
++?>
++--FILE--
++<?php
++include 'include.inc';
++
++$filename = __DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php";
++$script = '<?php echo "hello "; echo "world"; ?>';
++file_put_contents($filename, $script);
++
++$php = get_cgi_path();
++reset_env_vars();
++
++putenv("SERVER_NAME=Test");
++putenv("SCRIPT_FILENAME=$filename");
++putenv("QUERY_STRING=%ads");
++putenv("REDIRECT_STATUS=1");
++
++passthru("$php -s");
++
++?>
++--CLEAN--
++<?php
++@unlink(__DIR__."/GHSA-3qgc-jrrr-25jv_tmp.php");
++?>
++--EXPECTF--
++X-Powered-By: PHP/%s
++Content-type: %s
++
++hello world
+--
+2.46.1
+
+From c5daf2e9cc0bc6b6587b67de97b9cb188898da8e Mon Sep 17 00:00:00 2001
+From: Jan Ehrhardt <github@ehrhardt.nl>
+Date: Thu, 6 Jun 2024 23:48:14 +0200
+Subject: [PATCH 2/9] Fix GHSA-3qgc-jrrr-25jv - VC11
+
+---
+ sapi/cgi/cgi_main.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
+index 1996eb6e87..3051a89bce 100644
+--- a/sapi/cgi/cgi_main.c
++++ b/sapi/cgi/cgi_main.c
+@@ -1851,10 +1851,12 @@ int main(int argc, char *argv[])
+ #ifdef PHP_WIN32
+ if (*p >= 0x80) {
+ wchar_t wide_buf[1];
+- wide_buf[0] = *p;
+ char char_buf[4];
+- size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
+- size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
++ size_t wide_buf_len;
++ size_t char_buf_len;
++ wide_buf[0] = *p;
++ wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
++ char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
+ if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0
+ || char_buf[0] == '-') {
+ skip_getopt = 1;
+--
+2.46.1
+
+From ed5aebf7d65fb67b399f9320f704b5e2bb165117 Mon Sep 17 00:00:00 2001
+From: Jan Ehrhardt <github@ehrhardt.nl>
+Date: Sun, 9 Jun 2024 20:15:52 +0200
+Subject: [PATCH 3/9] NEWS: Add backport from 8.1.29
+
+---
+ NEWS | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index c10febbfa1..b4be05a2d2 100644
+--- a/NEWS
++++ b/NEWS
+@@ -3,6 +3,10 @@ PHP NEWS
+
+ Backported from 8.1.29
+
++- CGI:
++ . Fixed bug GHSA-3qgc-jrrr-25jv (Bypass of CVE-2012-1823, Argument Injection
++ in PHP-CGI). (CVE-2024-4577) (nielsdos)
++
+ - Filter:
+ . Fixed bug GHSA-w8qr-v226-r27w (Filter bypass in filter_var FILTER_VALIDATE_URL).
+ (CVE-2024-5458) (nielsdos)
+--
+2.46.1
+
+From d371734993ed88e9ef42c47430ae8097c5ee03f0 Mon Sep 17 00:00:00 2001
+From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
+Date: Fri, 14 Jun 2024 19:49:22 +0200
+Subject: [PATCH 5/9] Fix GHSA-p99j-rfp4-xqvq
+
+It's no use trying to work around whatever the operating system and Apache
+do because we'll be fighting that until eternity.
+Change the skip_getopt condition such that when we're running in
+CGI or FastCGI mode we always skip the argument parsing.
+This is a BC break, but this seems to be the only way to get rid of this
+class of issues.
+
+(cherry picked from commit abcfd980bfa03298792fd3aba051c78d52f10642)
+(cherry picked from commit 2d2552e092b6ff32cd823692d512f126ee629842)
+(cherry picked from commit 1158d06f0b20532ab7309cb20f0be843f9662e3c)
+(cherry picked from commit 89c66773413267949de995671bfb4bd03c34fbf9)
+(cherry picked from commit 53a0269aa1d952eec1c65e0e0d3e9800e0427ded)
+(cherry picked from commit 56f24340b2cd718d54fca9bc95cbf1f34b50b71f)
+(cherry picked from commit 493b4986d3cb8bfaccbab82628a4b91044670572)
+---
+ sapi/cgi/cgi_main.c | 25 +++++++------------------
+ 1 file changed, 7 insertions(+), 18 deletions(-)
+
+diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
+index 3051a89bce..60b8e981cc 100644
+--- a/sapi/cgi/cgi_main.c
++++ b/sapi/cgi/cgi_main.c
+@@ -1835,8 +1835,13 @@ int main(int argc, char *argv[])
+ * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode,
+ * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`.
+ * Therefore, this code only prevents passing arguments if the query string starts with a '-'.
+- * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */
++ * Similarly, scripts spawned in subprocesses on Windows may have the same issue.
++ * However, Windows has lots of conversion rules and command line parsing rules that
++ * are too difficult and dangerous to reliably emulate. */
+ if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
++#ifdef PHP_WIN32
++ skip_getopt = cgi || fastcgi;
++#else
+ unsigned char *p;
+ decoded_query_string = strdup(query_string);
+ php_url_decode(decoded_query_string, strlen(decoded_query_string));
+@@ -1847,24 +1852,8 @@ int main(int argc, char *argv[])
+ skip_getopt = 1;
+ }
+
+- /* On Windows we have to take into account the "best fit" mapping behaviour. */
+-#ifdef PHP_WIN32
+- if (*p >= 0x80) {
+- wchar_t wide_buf[1];
+- char char_buf[4];
+- size_t wide_buf_len;
+- size_t char_buf_len;
+- wide_buf[0] = *p;
+- wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]);
+- char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]);
+- if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0
+- || char_buf[0] == '-') {
+- skip_getopt = 1;
+- }
+- }
+-#endif
+-
+ free(decoded_query_string);
++#endif
+ }
+
+ while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
+--
+2.46.1
+