mirror of
https://github.com/php/php-src.git
synced 2026-04-11 01:53:36 +02:00
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/>
This commit is contained in:
committed by
Patrick Allaert
parent
7fd14eb08b
commit
4ef300ff5e
2
NEWS
2
NEWS
@@ -3,6 +3,8 @@ PHP NEWS
|
||||
?? ??? ????, PHP 8.1.11
|
||||
|
||||
- Core:
|
||||
. Fixed bug #81726: phar wrapper: DOS when using quine gzip file.
|
||||
(CVE-2022-31628). (cmb)
|
||||
. Fixed bug GH-9323 (Crash in ZEND_RETURN/GC/zend_call_function)
|
||||
(Tim Starling)
|
||||
. Fixed bug GH-9361 (Segmentation fault on script exit #9379). (cmb,
|
||||
|
||||
@@ -1626,7 +1626,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);
|
||||
@@ -1654,8 +1655,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;
|
||||
@@ -1715,7 +1715,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;
|
||||
@@ -1753,7 +1756,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;
|
||||
}
|
||||
|
||||
|
||||
BIN
ext/phar/tests/bug81726.gz
Normal file
BIN
ext/phar/tests/bug81726.gz
Normal file
Binary file not shown.
14
ext/phar/tests/bug81726.phpt
Normal file
14
ext/phar/tests/bug81726.phpt
Normal file
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Bug #81726 (phar wrapper: DOS when using quine gzip file)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("phar")) die("skip phar extension not available");
|
||||
if (!extension_loaded("zlib")) die("skip zlib extension not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(fopen("phar://" . __DIR__ . "/bug81726.gz", "r"));
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: fopen(phar://%s): failed to open stream: unable to decompress gzipped phar archive "%s" in %s on line %d
|
||||
bool(false)
|
||||
Reference in New Issue
Block a user