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
196
197
198
199
200
201
202
203
204
205
206
207
|
From cdabc241c4f631ffa87e2652fe241184f519618f Mon Sep 17 00:00:00 2001
From: "Christoph M. Becker" <cmbecker69@gmx.de>
Date: Tue, 1 Sep 2020 10:04:28 +0200
Subject: [PATCH 1/3] Fix #79971: special character is breaking the path in xml
function
The libxml based XML functions accepting a filename actually accept
URIs with possibly percent-encoded characters. Percent-encoded NUL
bytes lead to truncation, like non-encoded NUL bytes would. We catch
those, and let the functions fail with a respective warning.
(cherry picked from commit f15f8fc573eb38c3c73e23e0930063a6f6409ed4)
---
ext/dom/domimplementation.c | 5 +++++
ext/dom/tests/bug79971_2.phpt | 20 ++++++++++++++++++++
ext/libxml/libxml.c | 9 +++++++++
ext/simplexml/tests/bug79971_1.phpt | 27 +++++++++++++++++++++++++++
ext/simplexml/tests/bug79971_1.xml | 2 ++
5 files changed, 63 insertions(+)
create mode 100644 ext/dom/tests/bug79971_2.phpt
create mode 100644 ext/simplexml/tests/bug79971_1.phpt
create mode 100644 ext/simplexml/tests/bug79971_1.xml
diff --git a/ext/dom/domimplementation.c b/ext/dom/domimplementation.c
index 28e35eb785..f4d1358b8e 100644
--- a/ext/dom/domimplementation.c
+++ b/ext/dom/domimplementation.c
@@ -114,6 +114,11 @@ PHP_METHOD(domimplementation, createDocumentType)
pch2 = (xmlChar *) systemid;
}
+ if (strstr(name, "%00")) {
+ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
+ RETURN_FALSE;
+ }
+
uri = xmlParseURI(name);
if (uri != NULL && uri->opaque != NULL) {
localname = xmlStrdup((xmlChar *) uri->opaque);
diff --git a/ext/dom/tests/bug79971_2.phpt b/ext/dom/tests/bug79971_2.phpt
new file mode 100644
index 0000000000..c4e6b1e4e0
--- /dev/null
+++ b/ext/dom/tests/bug79971_2.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #79971 (special character is breaking the path in xml function)
+--SKIPIF--
+<?php
+if (!extension_loaded('dom')) die('skip dom extension not available');
+?>
+--FILE--
+<?php
+$imp = new DOMImplementation;
+if (PHP_OS_FAMILY === 'Windows') {
+ $path = '/' . str_replace('\\', '/', __DIR__);
+} else {
+ $path = __DIR__;
+}
+$uri = "file://$path/bug79971_2.xml";
+var_dump($imp->createDocumentType("$uri%00foo"));
+?>
+--EXPECTF--
+Warning: DOMImplementation::createDocumentType(): URI must not contain percent-encoded NUL bytes in %s on line %d
+bool(false)
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 85f239d5c7..98344d1d56 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -308,6 +308,10 @@ static void *php_libxml_streams_IO_open_wrapper(const char *filename, const char
int isescaped=0;
xmlURI *uri;
+ if (strstr(filename, "%00")) {
+ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
+ return NULL;
+ }
uri = xmlParseURI(filename);
if (uri && (uri->scheme == NULL ||
@@ -438,6 +442,11 @@ php_libxml_output_buffer_create_filename(const char *URI,
if (URI == NULL)
return(NULL);
+ if (strstr(URI, "%00")) {
+ php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
+ return NULL;
+ }
+
puri = xmlParseURI(URI);
if (puri != NULL) {
if (puri->scheme != NULL)
diff --git a/ext/simplexml/tests/bug79971_1.phpt b/ext/simplexml/tests/bug79971_1.phpt
new file mode 100644
index 0000000000..197776d82d
--- /dev/null
+++ b/ext/simplexml/tests/bug79971_1.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #79971 (special character is breaking the path in xml function)
+--SKIPIF--
+<?php
+if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
+?>
+--FILE--
+<?php
+if (PHP_OS_FAMILY === 'Windows') {
+ $path = '/' . str_replace('\\', '/', __DIR__);
+} else {
+ $path = __DIR__;
+}
+$uri = "file://$path/bug79971_1.xml";
+var_dump(simplexml_load_file("$uri%00foo"));
+
+$sxe = simplexml_load_file($uri);
+var_dump($sxe->asXML("$uri.out%00foo"));
+?>
+--EXPECTF--
+Warning: simplexml_load_file(): URI must not contain percent-encoded NUL bytes in %s on line %d
+
+Warning: simplexml_load_file(): I/O warning : failed to load external entity "%s/bug79971_1.xml%00foo" in %s on line %d
+bool(false)
+
+Warning: SimpleXMLElement::asXML(): URI must not contain percent-encoded NUL bytes in %s on line %d
+bool(false)
diff --git a/ext/simplexml/tests/bug79971_1.xml b/ext/simplexml/tests/bug79971_1.xml
new file mode 100644
index 0000000000..912bb76d9d
--- /dev/null
+++ b/ext/simplexml/tests/bug79971_1.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<root></root>
--
2.31.1
From d2a6660b7942b3b8e4f0e31f3b061dacb4d0b87d Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@remirepo.net>
Date: Mon, 15 Nov 2021 09:05:33 +0100
Subject: [PATCH 2/3] NEWS
(cherry picked from commit c032381da0bfb6457aa9cfa7a430790f6eab8178)
---
NEWS | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/NEWS b/NEWS
index c0e4078a7b..e5c20296ed 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,13 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-Backported from 7.4.25
+Backported from 7.3.33
+
+- XML:
+ . Fix #79971: special character is breaking the path in xml function.
+ (CVE-2021-21707) (cmb)
+
+Backported from 7.3.32
- FPM:
. Fixed bug #81026 (PHP-FPM oob R/W in root process leading to privilege
--
2.31.1
From b21524ff3db15da5a7779cba73e3774eb5404d40 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@remirepo.net>
Date: Mon, 15 Nov 2021 09:57:10 +0100
Subject: [PATCH 3/3] fix new tests
---
ext/dom/tests/bug79971_2.phpt | 2 +-
ext/simplexml/tests/bug79971_1.phpt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/ext/dom/tests/bug79971_2.phpt b/ext/dom/tests/bug79971_2.phpt
index c4e6b1e4e0..01cd123541 100644
--- a/ext/dom/tests/bug79971_2.phpt
+++ b/ext/dom/tests/bug79971_2.phpt
@@ -7,7 +7,7 @@ if (!extension_loaded('dom')) die('skip dom extension not available');
--FILE--
<?php
$imp = new DOMImplementation;
-if (PHP_OS_FAMILY === 'Windows') {
+if (DIRECTORY_SEPARATOR !== '/') {
$path = '/' . str_replace('\\', '/', __DIR__);
} else {
$path = __DIR__;
diff --git a/ext/simplexml/tests/bug79971_1.phpt b/ext/simplexml/tests/bug79971_1.phpt
index 197776d82d..464112c99e 100644
--- a/ext/simplexml/tests/bug79971_1.phpt
+++ b/ext/simplexml/tests/bug79971_1.phpt
@@ -6,7 +6,7 @@ if (!extension_loaded('simplexml')) die('skip simplexml extension not available'
?>
--FILE--
<?php
-if (PHP_OS_FAMILY === 'Windows') {
+if (DIRECTORY_SEPARATOR !== '/') {
$path = '/' . str_replace('\\', '/', __DIR__);
} else {
$path = __DIR__;
--
2.31.1
|