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
|
From 96fda78bcddd1d793cf2d0ee463dbb49621b577f Mon Sep 17 00:00:00 2001
From: "Christoph M. Becker" <cmbecker69@gmx.de>
Date: Mon, 25 Jul 2022 15:58:59 +0200
Subject: [PATCH] Fix #81726: phar wrapper: DOS when using quine gzip file
The phar wrapper needs to uncompress the file; the uncompressed file
might be compressed, so the wrapper implementation loops. This raises
potential DOS issues regarding too deep or even infinite recursion (the
latter are called compressed file quines[1]). We avoid that by
introducing a recursion limit; we choose the somewhat arbitrary limit
`3`.
This issue has been reported by real_as3617 and gPayl0ad.
[1] <https://honno.dev/gzip-quine/>
(cherry picked from commit 404e8bdb68350931176a5bdc86fc417b34fb583d)
---
NEWS | 2 ++
ext/phar/phar.c | 16 +++++++++++-----
ext/phar/tests/bug81726.gz | Bin 0 -> 204 bytes
ext/phar/tests/bug81726.phpt | 14 ++++++++++++++
4 files changed, 27 insertions(+), 5 deletions(-)
create mode 100644 ext/phar/tests/bug81726.gz
create mode 100644 ext/phar/tests/bug81726.phpt
diff --git a/NEWS b/NEWS
index 87b67643f3..fe4cb9c484 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ PHP NEWS
Backported from 7.4.31
- Core:
+ . Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
+ (CVE-2022-31628). (cmb)
. Fixed bug #81727: Don't mangle HTTP variable names that clash with ones
that have a specific semantic meaning. (CVE-2022-31629). (Derick)
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 44e40d98d1..9360658cd7 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -1593,7 +1593,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
const char zip_magic[] = "PK\x03\x04";
const char gz_magic[] = "\x1f\x8b\x08";
const char bz_magic[] = "BZh";
- char *pos, test = '\0';
+ char *pos;
+ int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion
const int window_size = 1024;
char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */
const zend_long readsize = sizeof(buffer) - sizeof(token);
@@ -1621,8 +1622,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
}
- if (!test) {
- test = '\1';
+ if (recursion_count) {
pos = buffer+tokenlen;
if (!memcmp(pos, gz_magic, 3)) {
char err = 0;
@@ -1682,7 +1682,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
compression = PHAR_FILE_COMPRESSED_GZ;
/* now, start over */
- test = '\0';
+ if (!--recursion_count) {
+ MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\"");
+ break;
+ }
continue;
} else if (!memcmp(pos, bz_magic, 3)) {
php_stream_filter *filter;
@@ -1720,7 +1723,10 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
compression = PHAR_FILE_COMPRESSED_BZ2;
/* now, start over */
- test = '\0';
+ if (!--recursion_count) {
+ MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\"");
+ break;
+ }
continue;
}
From 535c3f592d020a3a43f4ce3577e505d64297b6e8 Mon Sep 17 00:00:00 2001
From: "Christoph M. Becker" <cmbecker69@gmx.de>
Date: Tue, 27 Sep 2022 17:43:40 +0200
Subject: [PATCH] Fix regression introduced by fixing bug 81726
When a tar phar is created, `phar_open_from_fp()` is also called, but
since the file has just been created, none of the format checks can
succeed, so we continue to loop, but must not check again for the
format. Therefore, we bring back the old `test` variable.
Closes GH-9620.
(cherry picked from commit 432bf196d59bcb661fcf9cb7029cea9b43f490af)
---
ext/phar/phar.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 9360658cd7..1437525245 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -1593,7 +1593,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
const char zip_magic[] = "PK\x03\x04";
const char gz_magic[] = "\x1f\x8b\x08";
const char bz_magic[] = "BZh";
- char *pos;
+ char *pos, test = '\0';
int recursion_count = 3; // arbitrary limit to avoid too deep or even infinite recursion
const int window_size = 1024;
char buffer[1024 + sizeof(token)]; /* a 1024 byte window + the size of the halt_compiler token (moving window) */
@@ -1622,7 +1622,8 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
MAPPHAR_ALLOC_FAIL("internal corruption of phar \"%s\" (truncated entry)")
}
- if (recursion_count) {
+ if (!test && recursion_count) {
+ test = '\1';
pos = buffer+tokenlen;
if (!memcmp(pos, gz_magic, 3)) {
char err = 0;
@@ -1682,6 +1683,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
compression = PHAR_FILE_COMPRESSED_GZ;
/* now, start over */
+ test = '\0';
if (!--recursion_count) {
MAPPHAR_ALLOC_FAIL("unable to decompress gzipped phar archive \"%s\"");
break;
@@ -1723,6 +1725,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char
compression = PHAR_FILE_COMPRESSED_BZ2;
/* now, start over */
+ test = '\0';
if (!--recursion_count) {
MAPPHAR_ALLOC_FAIL("unable to decompress bzipped phar archive \"%s\"");
break;
--
2.37.3
From 9d32d284b25f5df75780911a47b3c23cbaac1761 Mon Sep 17 00:00:00 2001
From: Remi Collet <remi@remirepo.net>
Date: Fri, 30 Sep 2022 09:22:14 +0200
Subject: [PATCH] fix NEWS
---
NEWS | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index fe4cb9c484..b7a19aea19 100644
--- a/NEWS
+++ b/NEWS
@@ -1,14 +1,16 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-Backported from 7.4.31
+Backported from 7.4.32
- Core:
- . Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
- (CVE-2022-31628). (cmb)
. Fixed bug #81727: Don't mangle HTTP variable names that clash with ones
that have a specific semantic meaning. (CVE-2022-31629). (Derick)
+- Phar:
+ . Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
+ (CVE-2022-31628). (cmb)
+
Backported from 7.4.30
- mysqlnd:
|