Created
July 25, 2022 14:00
-
-
Save cmb69/77ad17bf57c6ef35785476d5328b4b74 to your computer and use it in GitHub Desktop.
Suggested patch for PHP bug #81726
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 0976bf346d6e4565ac9c3dfca8d431487601b6d0 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 | |
`100`. | |
This issue has been reported by real_as3617 and gPayl0ad. | |
[1] <https://honno.dev/gzip-quine/> | |
--- | |
ext/phar/phar.c | 16 +++++++++++----- | |
ext/phar/tests/bug81726.gz | Bin 0 -> 204 bytes | |
ext/phar/tests/bug81726.phpt | 14 ++++++++++++++ | |
3 files changed, 25 insertions(+), 5 deletions(-) | |
create mode 100644 ext/phar/tests/bug81726.gz | |
create mode 100644 ext/phar/tests/bug81726.phpt | |
diff --git a/ext/phar/phar.c b/ext/phar/phar.c | |
index 7cb1b06363..d3e6225d16 100644 | |
--- a/ext/phar/phar.c | |
+++ b/ext/phar/phar.c | |
@@ -1584,7 +1584,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 = 100; // 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); | |
@@ -1612,8 +1613,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; | |
@@ -1673,7 +1673,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; | |
@@ -1711,7 +1714,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; | |
} | |
diff --git a/ext/phar/tests/bug81726.gz b/ext/phar/tests/bug81726.gz | |
new file mode 100644 | |
index 0000000000000000000000000000000000000000..67b41ba3b6567fb242296fbb5db1504dd562c285 | |
GIT binary patch | |
literal 204 | |
zcmb2|=HOref&Yc2nR%&t=~WC25)9A(%i|Dt5_1=0XJBRc^&i0ka~VV!USk*QP&~o_ | |
nktKo!bjW{@YyLCvGJN{)1lEBn)?BbahT(tZ|CMKe>QFcU?_ozX | |
literal 0 | |
HcmV?d00001 | |
diff --git a/ext/phar/tests/bug81726.phpt b/ext/phar/tests/bug81726.phpt | |
new file mode 100644 | |
index 0000000000..11a148c28e | |
--- /dev/null | |
+++ b/ext/phar/tests/bug81726.phpt | |
@@ -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) | |
-- | |
2.37.1.windows.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment