summaryrefslogtreecommitdiffstats
path: root/php-cve-2024-2756.patch
blob: a8607d95f4d4aa9443530d08dd0805186403b144 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
From 46b570a1e4aeb4a414898fcc09503ac388d16256 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Sun, 17 Mar 2024 21:04:47 +0100
Subject: [PATCH 1/4] Fix GHSA-wpj3-hf5j-x4v4: __Host-/__Secure- cookie bypass
 due to partial CVE-2022-31629 fix

The check happened too early as later code paths may perform more
mangling rules. Move the check downwards right before adding the actual
variable.

(cherry picked from commit 093c08af25fb323efa0c8e6154aa9fdeae3d3b53)
(cherry picked from commit 2e07a3acd7a6b53c55325b94bed97748d7697b53)
(cherry picked from commit a6c1c62a25ac23b08a86af11d68f0e2eaafc102b)
---
 ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt | 63 +++++++++++++++++++++
 main/php_variables.c                        | 41 +++++++++-----
 2 files changed, 90 insertions(+), 14 deletions(-)
 create mode 100644 ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt

diff --git a/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt
new file mode 100644
index 0000000000..77fcb68089
--- /dev/null
+++ b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt
@@ -0,0 +1,63 @@
+--TEST--
+ghsa-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix)
+--COOKIE--
+..Host-test=ignore_1;
+._Host-test=ignore_2;
+.[Host-test=ignore_3;
+_.Host-test=ignore_4;
+__Host-test=ignore_5;
+_[Host-test=ignore_6;
+[.Host-test=ignore_7;
+[_Host-test=ignore_8;
+[[Host-test=ignore_9;
+..Host-test[]=ignore_10;
+._Host-test[]=ignore_11;
+.[Host-test[]=ignore_12;
+_.Host-test[]=ignore_13;
+__Host-test[]=legitimate_14;
+_[Host-test[]=legitimate_15;
+[.Host-test[]=ignore_16;
+[_Host-test[]=ignore_17;
+[[Host-test[]=ignore_18;
+..Secure-test=ignore_1;
+._Secure-test=ignore_2;
+.[Secure-test=ignore_3;
+_.Secure-test=ignore_4;
+__Secure-test=ignore_5;
+_[Secure-test=ignore_6;
+[.Secure-test=ignore_7;
+[_Secure-test=ignore_8;
+[[Secure-test=ignore_9;
+..Secure-test[]=ignore_10;
+._Secure-test[]=ignore_11;
+.[Secure-test[]=ignore_12;
+_.Secure-test[]=ignore_13;
+__Secure-test[]=legitimate_14;
+_[Secure-test[]=legitimate_15;
+[.Secure-test[]=ignore_16;
+[_Secure-test[]=ignore_17;
+[[Secure-test[]=ignore_18;
+--FILE--
+<?php
+var_dump($_COOKIE);
+?>
+--EXPECT--
+array(3) {
+  ["__Host-test"]=>
+  array(1) {
+    [0]=>
+    string(13) "legitimate_14"
+  }
+  ["_"]=>
+  array(2) {
+    ["Host-test["]=>
+    string(13) "legitimate_15"
+    ["Secure-test["]=>
+    string(13) "legitimate_15"
+  }
+  ["__Secure-test"]=>
+  array(1) {
+    [0]=>
+    string(13) "legitimate_14"
+  }
+}
diff --git a/main/php_variables.c b/main/php_variables.c
index f2d0c3bd98..d0ebd50ec8 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -65,6 +65,21 @@ static zend_always_inline void php_register_variable_quick(const char *name, siz
 	zend_string_release_ex(key, 0);
 }
 
+/* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host-
+ * Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */
+static zend_bool php_is_forbidden_variable_name(const char *mangled_name, size_t mangled_name_len, const char *pre_mangled_name)
+{
+	if (mangled_name_len >= sizeof("__Host-")-1 && strncmp(mangled_name, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(pre_mangled_name, "__Host-", sizeof("__Host-")-1) != 0) {
+		return 1;
+	}
+
+	if (mangled_name_len >= sizeof("__Secure-")-1 && strncmp(mangled_name, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(pre_mangled_name, "__Secure-", sizeof("__Secure-")-1) != 0) {
+		return 1;
+	}
+
+	return 0;
+}
+
 PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array)
 {
 	char *p = NULL;
@@ -115,20 +130,6 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
 	}
 	var_len = p - var;
 
-	/* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */
-	if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) {
-		zval_ptr_dtor_nogc(val);
-		free_alloca(var_orig, use_heap);
-		return;
-	}
-
-	/* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */
-	if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) {
-		zval_ptr_dtor_nogc(val);
-		free_alloca(var_orig, use_heap);
-		return;
-	}
-
 	if (var_len==0) { /* empty variable name, or variable name with a space in it */
 		zval_ptr_dtor_nogc(val);
 		free_alloca(var_orig, use_heap);
@@ -226,6 +227,12 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
 					return;
 				}
 			} else {
+				if (php_is_forbidden_variable_name(index, index_len, var_name)) {
+					zval_ptr_dtor_nogc(val);
+					free_alloca(var_orig, use_heap);
+					return;
+				}
+
 				gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
 				if (!gpc_element_p) {
 					zval tmp;
@@ -263,6 +270,12 @@ plain_var:
 				zval_ptr_dtor_nogc(val);
 			}
 		} else {
+			if (php_is_forbidden_variable_name(index, index_len, var_name)) {
+				zval_ptr_dtor_nogc(val);
+				free_alloca(var_orig, use_heap);
+				return;
+			}
+
 			zend_ulong idx;
 
 			/*
-- 
2.44.0

From 8642473b624f809b768180b104c013f74e3a99a0 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@remirepo.net>
Date: Wed, 10 Apr 2024 08:59:32 +0200
Subject: [PATCH 2/4] NEWS

(cherry picked from commit 366cc249b7d54707572beb7096e8f6c65ee79719)
(cherry picked from commit dcdd49ef3bfbd8ccc778850d6a0f9b98adf625d4)
---
 NEWS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/NEWS b/NEWS
index 05d9ca8f4c..e26f978213 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,12 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 
+Backported from 8.1.28
+
+- Standard:
+  . Fixed bug GHSA-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to
+    partial CVE-2022-31629 fix). (CVE-2024-2756) (nielsdos)
+
 Backported from 8.0.30
 
 - Libxml:
-- 
2.44.0