Skip to content

Commit c5f24a1

Browse files
fix: loop the :// strip in detaintPath so it cannot be re-formed
detaintPath() and detaintPathAllowAbsolute() removed '://' with a single str_replace() while the '../' removal below them already looped. One pass is not enough, because removing a match can join its neighbours into a fresh match: '::////' collapses to '://'. So 'php::////filter/read=string.rot13/resource=/etc/passwd' came back out of the filter as 'php://filter/read=string.rot13/resource=/etc/passwd', reinstating exactly the wrapper the strip exists to remove. Loop the '://' removal the same way the '../' removal is looped. These functions guard $view, $request, $action, the modal name and skin file paths. Refs GHSA-wgqf-6fjf-7gxw. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6daa135 commit c5f24a1

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

web/includes/functions.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,8 +1823,12 @@ function generateConnKey() {
18231823
}
18241824

18251825
function detaintPathAllowAbsolute($path) {
1826-
// Strip out :// because php:// is a way to inject code apparently
1827-
$path = str_replace('://', '', $path);
1826+
// Strip out :// because php:// is a way to inject code apparently.
1827+
// This must loop: a single pass lets the removal re-form the sequence it
1828+
// just removed, so '::////' collapses back into '://'.
1829+
do {
1830+
$path = str_replace('://', '', $path, $count);
1831+
} while($count);
18281832
// Remove any absolute paths, or relative ones that want to go up
18291833
do {
18301834
$path = str_replace('../', '', $path, $count);
@@ -1834,8 +1838,12 @@ function detaintPathAllowAbsolute($path) {
18341838

18351839
function detaintPath($path) {
18361840

1837-
// Strip out :// because php:// is a way to inject code apparently
1838-
$path = str_replace('://', '', $path);
1841+
// Strip out :// because php:// is a way to inject code apparently.
1842+
// This must loop: a single pass lets the removal re-form the sequence it
1843+
// just removed, so '::////' collapses back into '://'.
1844+
do {
1845+
$path = str_replace('://', '', $path, $count);
1846+
} while($count);
18391847
// Remove any absolute paths, or relative ones that want to go up
18401848
do {
18411849
$path = str_replace('../', '', $path, $count);

0 commit comments

Comments
 (0)