Skip to content

Commit 2ff2085

Browse files
lazergLamentXU123
authored andcommitted
Fix GH-25093: Phar::webPhar() redirect reads past the request URI (#25102)
On non-CGI SAPIs, a direct request advances a pointer into the request URI by the length of the full phar path. This can read past the URI, including when a rewrite callback returns '/'. Advance by the basename length, as the target path construction does. Add a regression test and a NEWS entry. Closes #25102
1 parent 7091e5b commit 2ff2085

3 files changed

Lines changed: 50 additions & 1 deletion

File tree

‎NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ PHP NEWS
238238
(mvorisek)
239239

240240
- Phar:
241+
. Fixed bug GH-25093 (Phar::webPhar() redirect reads past the request URI).
242+
(lazerg)
241243
. Fixed bug GH-25089 (Heap buffer over-read via crafted alias size in
242244
zip-based phar). (Lazizbek Ergashev)
243245
. Fixed bug GH-8469 (Phar::decompressFiles() and Phar::compressFiles() retain

‎ext/phar/phar_object.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ PHP_METHOD(Phar, webPhar)
784784
sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
785785

786786
if (not_cgi) {
787-
tmp = strstr(path_info, basename) + fname_len;
787+
tmp = strstr(path_info, basename) + (fname_len - (basename - fname));
788788
sa = *tmp;
789789
*tmp = '\0';
790790
}

‎ext/phar/tests/gh25093.phpt‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
GH-25093: Phar::webPhar() redirect reads past the request URI
3+
--EXTENSIONS--
4+
phar
5+
--SKIPIF--
6+
<?php
7+
if (!file_exists(__DIR__ . "/../../../sapi/cli/tests/php_cli_server.inc")) {
8+
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
9+
}
10+
?>
11+
--CONFLICTS--
12+
server
13+
--INI--
14+
phar.readonly=0
15+
phar.require_hash=0
16+
--FILE--
17+
<?php
18+
include __DIR__ . "/../../../sapi/cli/tests/php_cli_server.inc";
19+
20+
$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "phar." . PHP_SHLIB_SUFFIX];
21+
if (php_ini_loaded_file()) {
22+
$args[] = "-c";
23+
$args[] = php_ini_loaded_file();
24+
}
25+
$info = php_cli_server_start('include __DIR__ . "/gh25093.phar";', 'router.php', $args);
26+
27+
$phar = new Phar($info->docRoot . '/gh25093.phar');
28+
$phar->addFromString('index.php', '<?php echo "index\n";');
29+
$phar->setStub('<?php
30+
Phar::webPhar(null, "index.php", null, [], function ($path) {
31+
return "/";
32+
});
33+
__HALT_COMPILER(); ?>');
34+
unset($phar);
35+
36+
$context = stream_context_create(['http' => ['follow_location' => 0]]);
37+
$uri = '/gh25093.phar/' . str_repeat('a', strlen($info->docRoot) + 32);
38+
file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . $uri, false, $context);
39+
40+
foreach (http_get_last_response_headers() as $header) {
41+
if (str_starts_with($header, 'Location: ')) {
42+
echo $header, "\n";
43+
}
44+
}
45+
?>
46+
--EXPECT--
47+
Location: /gh25093.phar/index.php

0 commit comments

Comments
 (0)