1
0
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:
Christoph M. Becker
2022-07-25 15:58:59 +02:00
committed by Patrick Allaert
parent 7fd14eb08b
commit 4ef300ff5e
4 changed files with 27 additions and 5 deletions

2
NEWS
View File

@@ -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,

View File

@@ -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

Binary file not shown.

View 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)