From c5f24a1d1fb42a047a51ecf71cc39bc3e33f61ba Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sun, 19 Jul 2026 13:13:06 -0400 Subject: [PATCH] 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) --- web/includes/functions.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index 19b3cf11c..99307c79c 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -1823,8 +1823,12 @@ function generateConnKey() { } function detaintPathAllowAbsolute($path) { - // Strip out :// because php:// is a way to inject code apparently - $path = str_replace('://', '', $path); + // Strip out :// because php:// is a way to inject code apparently. + // This must loop: a single pass lets the removal re-form the sequence it + // just removed, so '::////' collapses back into '://'. + do { + $path = str_replace('://', '', $path, $count); + } while($count); // Remove any absolute paths, or relative ones that want to go up do { $path = str_replace('../', '', $path, $count); @@ -1834,8 +1838,12 @@ function detaintPathAllowAbsolute($path) { function detaintPath($path) { - // Strip out :// because php:// is a way to inject code apparently - $path = str_replace('://', '', $path); + // Strip out :// because php:// is a way to inject code apparently. + // This must loop: a single pass lets the removal re-form the sequence it + // just removed, so '::////' collapses back into '://'. + do { + $path = str_replace('://', '', $path, $count); + } while($count); // Remove any absolute paths, or relative ones that want to go up do { $path = str_replace('../', '', $path, $count);