diff options
author | Remi Collet <remi@remirepo.net> | 2021-08-26 09:19:48 +0200 |
---|---|---|
committer | Remi Collet <remi@remirepo.net> | 2021-08-26 09:19:48 +0200 |
commit | dc8343ac30f73c1662088e4981436ed2dbd936af (patch) | |
tree | 8b24f9cc45f50e4979736d05a5f7c3601fafd1f1 | |
parent | a0041d33040364f1b12e6c94cba82c46d1f57fc1 (diff) |
Fix #81211 Symlinks are followed when creating PHAR archive
-rw-r--r-- | php-bug81211.patch | 164 | ||||
-rw-r--r-- | php.spec | 7 |
2 files changed, 170 insertions, 1 deletions
diff --git a/php-bug81211.patch b/php-bug81211.patch new file mode 100644 index 0000000..c2ab931 --- /dev/null +++ b/php-bug81211.patch @@ -0,0 +1,164 @@ +From ac8faf81d2f142edae91c81f17530a6bf01114dd Mon Sep 17 00:00:00 2001 +From: "Christoph M. Becker" <cmbecker69@gmx.de> +Date: Mon, 23 Aug 2021 13:42:17 +0200 +Subject: [PATCH 1/3] Fix #81211: Symlinks are followed when creating PHAR + archive + +It is insufficient to check whether the `base` is contained in `fname`; +we also need to ensure that `fname` is properly separated. And of +course, `fname` has to start with `base`. + +(cherry picked from commit 2ff853aa113e52637c85e28d1a03df1aa2d747b5) +--- + ext/phar/phar_object.c | 3 +- + ext/phar/tests/bug81211.phpt | 45 +++++++++++++++++++ + .../tests/file/windows_links/common.inc | 9 +++- + 3 files changed, 55 insertions(+), 2 deletions(-) + create mode 100644 ext/phar/tests/bug81211.phpt + +diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c +index 5722828c37..55ac24728e 100644 +--- a/ext/phar/phar_object.c ++++ b/ext/phar/phar_object.c +@@ -1428,6 +1428,7 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ + phar_archive_object *phar_obj = p_obj->p; + char *str = "[stream]"; + php_stream_statbuf ssb; ++ char ch; + + iter->funcs->get_current_data(iter, &value TSRMLS_CC); + +@@ -1551,7 +1552,7 @@ phar_spl_fileinfo: + base = temp; + base_len = strlen(base); + +- if (strstr(fname, base)) { ++ if (fname_len >= base_len && strncmp(fname, base, base_len) == 0 && ((ch = fname[base_len - IS_SLASH(base[base_len - 1])]) == '\0' || IS_SLASH(ch))) { + str_key_len = fname_len - base_len; + + if (str_key_len <= 0) { +diff --git a/ext/phar/tests/bug81211.phpt b/ext/phar/tests/bug81211.phpt +new file mode 100644 +index 0000000000..43d82143f2 +--- /dev/null ++++ b/ext/phar/tests/bug81211.phpt +@@ -0,0 +1,45 @@ ++--TEST-- ++Bug #81211 (Symlinks are followed when creating PHAR archive) ++--SKIPIF-- ++<?php ++if (!extension_loaded('phar')) die('skip phar extension is not available'); ++if (PHP_OS_FAMILY === 'Windows') { ++ if (false === include __DIR__ . '/../../standard/tests/file/windows_links/common.inc') { ++ die('skip windows_links/common.inc is not available'); ++ } ++ skipIfSeCreateSymbolicLinkPrivilegeIsDisabled(__FILE__); ++} ++?> ++--FILE-- ++<?php ++mkdir(__DIR__ . '/bug81211'); ++mkdir(__DIR__ . '/bug81211/foobar'); ++mkdir(__DIR__ . '/bug81211/foo'); ++ ++file_put_contents(__DIR__ . '/bug81211/foobar/file', 'this file should NOT be included in the archive!'); ++symlink(__DIR__ . '/bug81211/foobar/file', __DIR__ . '/bug81211/foo/symlink'); ++ ++$archive = new PharData(__DIR__ . '/bug81211/archive.tar'); ++try { ++ $archive->buildFromDirectory(__DIR__ . '/bug81211/foo'); ++} catch (UnexpectedValueException $ex) { ++ echo $ex->getMessage(), PHP_EOL; ++} ++try { ++ $archive->buildFromIterator(new RecursiveDirectoryIterator(__DIR__ . '/bug81211/foo', FilesystemIterator::SKIP_DOTS), __DIR__ . '/bug81211/foo'); ++} catch (UnexpectedValueException $ex) { ++ echo $ex->getMessage(), PHP_EOL; ++} ++?> ++--CLEAN-- ++<?php ++@unlink(__DIR__ . '/bug81211/archive.tar'); ++@unlink(__DIR__ . '/bug81211/foo/symlink'); ++@unlink(__DIR__ . '/bug81211/foobar/file'); ++@rmdir(__DIR__ . '/bug81211/foo'); ++@rmdir(__DIR__ . '/bug81211/foobar'); ++@rmdir(__DIR__ . '/bug81211'); ++?> ++--EXPECTF-- ++Iterator RecursiveIteratorIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo" ++Iterator RecursiveDirectoryIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo" +diff --git a/ext/standard/tests/file/windows_links/common.inc b/ext/standard/tests/file/windows_links/common.inc +index 2d4b47cd51..936a1e31e8 100644 +--- a/ext/standard/tests/file/windows_links/common.inc ++++ b/ext/standard/tests/file/windows_links/common.inc +@@ -20,4 +20,11 @@ function get_mountvol() { + return "$sysroot\\System32\\mountvol.exe"; + } + +-?> ++function skipIfSeCreateSymbolicLinkPrivilegeIsDisabled(string $filename) { ++ $ln = "$filename.lnk"; ++ $ret = exec("mklink $ln " . __FILE__ .' 2>&1', $out); ++ @unlink($ln); ++ if (strpos($ret, 'privilege') !== false) { ++ die('skip SeCreateSymbolicLinkPrivilege not enabled'); ++ } ++} +-- +2.31.1 + +From f55897fd84f4ba99dd635fbeabef884f170d2bef Mon Sep 17 00:00:00 2001 +From: Stanislav Malyshev <stas@php.net> +Date: Mon, 23 Aug 2021 23:43:32 -0700 +Subject: [PATCH 2/3] Fix test + +(cherry picked from commit b815645aac76b494dc119fa6b88de32fa9bcccf1) +--- + ext/phar/tests/bug81211.phpt | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ext/phar/tests/bug81211.phpt b/ext/phar/tests/bug81211.phpt +index 43d82143f2..96b1401b40 100644 +--- a/ext/phar/tests/bug81211.phpt ++++ b/ext/phar/tests/bug81211.phpt +@@ -41,5 +41,5 @@ try { + @rmdir(__DIR__ . '/bug81211'); + ?> + --EXPECTF-- +-Iterator RecursiveIteratorIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo" +-Iterator RecursiveDirectoryIterator returned a path "%s%ebug81211\foobar\file" that is not in the base directory "%s%ebug81211\foo" ++Iterator RecursiveIteratorIterator returned a path "%s%ebug81211%efoobar%efile" that is not in the base directory "%s%ebug81211%efoo" ++Iterator RecursiveDirectoryIterator returned a path "%s%ebug81211%efoobar%efile" that is not in the base directory "%s%ebug81211%efoo" +-- +2.31.1 + +From caaa673e4ca008b7fa3f91538ec553c71d2fc97d Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Wed, 25 Aug 2021 15:23:50 +0200 +Subject: [PATCH 3/3] NEWS + +(cherry picked from commit 5539cefcda6aca7af220e7be7760a682abb88200) +--- + NEWS | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/NEWS b/NEWS +index 03d8a03ec1..c9cdc3a328 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,11 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 7.3.30 ++ ++- Phar: ++ . Fixed bug #81211: Symlinks are followed when creating PHAR archive (cmb) ++ + Backported from 7.3.29 + + - Core: +-- +2.31.1 + @@ -132,7 +132,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: %{?scl_prefix}php Version: 5.6.40 -Release: 28%{?dist} +Release: 29%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend # TSRM is licensed under BSD @@ -238,6 +238,7 @@ Patch248: php-bug80672.patch Patch249: php-bug80710.patch Patch250: php-bug81122.patch Patch251: php-bug76450.patch +Patch252: php-bug81211.patch # Fixes for tests (300+) # Factory is droped from system tzdata @@ -1018,6 +1019,7 @@ sed -e 's/php-devel/%{?scl_prefix}php-devel/' -i scripts/phpize.in %patch249 -p1 -b .bug80710 %patch250 -p1 -b .bug81122 %patch251 -p1 -b .bug76450 +%patch252 -p1 -b .bug81211 # Fixes for tests %patch300 -p1 -b .datetests @@ -1969,6 +1971,9 @@ EOF %changelog +* Thu Aug 26 2021 Remi Collet <remi@remirepo.net> - 5.6.40-29 +- Fix #81211 Symlinks are followed when creating PHAR archive + * Mon Jun 28 2021 Remi Collet <remi@remirepo.net> - 5.6.40-28 - Fix #81122 SSRF bypass in FILTER_VALIDATE_URL CVE-2021-21705 |