-
-
Notifications
You must be signed in to change notification settings - Fork 2
RC-scoped 3.6.4 fixes for PHP 8, dblayertrap, and filter loading #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
0e9c91d
98f081d
9443f97
25fe8fd
28b3052
89140bf
00f372c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -86,23 +86,67 @@ | |||||||||||||||||
| * | ||||||||||||||||||
| * @return int|mixed | ||||||||||||||||||
| */ | ||||||||||||||||||
| public function execute($type) | ||||||||||||||||||
|
Check failure on line 89 in htdocs/xoops_lib/modules/protector/class/ProtectorFilter.php
|
||||||||||||||||||
| { | ||||||||||||||||||
| $ret = 0; | ||||||||||||||||||
|
|
||||||||||||||||||
| $dh = opendir($this->filters_base); | ||||||||||||||||||
| if (false === $dh) { | ||||||||||||||||||
| return $ret; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // Fix 9.1: resolve the filters_enabled base path once so every candidate | ||||||||||||||||||
| // filter can be verified to live inside it. The previous loader included | ||||||||||||||||||
| // every file readdir() returned, which allowed a writable filters_enabled | ||||||||||||||||||
| // directory to achieve RCE if an attacker could place or symlink a file | ||||||||||||||||||
| // whose name happened to start with the requested type prefix. | ||||||||||||||||||
| // If realpath() fails (missing dir, broken symlink), bail out now — every | ||||||||||||||||||
| // per-file containment check below would fail the same way. | ||||||||||||||||||
| $baseReal = realpath($this->filters_base); | ||||||||||||||||||
| if (false === $baseReal) { | ||||||||||||||||||
| closedir($dh); | ||||||||||||||||||
| return $ret; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| while (($file = readdir($dh)) !== false) { | ||||||||||||||||||
| if (strncmp($file, $type . '_', strlen($type) + 1) === 0) { | ||||||||||||||||||
| include_once $this->filters_base . '/' . $file; | ||||||||||||||||||
| $plugin_name = 'protector_' . substr($file, 0, -4); | ||||||||||||||||||
| if (function_exists($plugin_name)) { | ||||||||||||||||||
| // old way | ||||||||||||||||||
| $ret |= call_user_func($plugin_name); | ||||||||||||||||||
| } elseif (class_exists($plugin_name)) { | ||||||||||||||||||
| // newer way | ||||||||||||||||||
| $plugin_obj = new $plugin_name(); //old code is -> $plugin_obj =& new $plugin_name() ; //hack by Trabis | ||||||||||||||||||
| $ret |= $plugin_obj->execute(); | ||||||||||||||||||
| } | ||||||||||||||||||
| if (strncmp($file, $type . '_', strlen($type) + 1) !== 0) { | ||||||||||||||||||
| continue; | ||||||||||||||||||
| } | ||||||||||||||||||
| // Require .php suffix — blocks .phtml, .inc, .phar and other executable | ||||||||||||||||||
| // extensions that may be interpreted as PHP by misconfigured servers. | ||||||||||||||||||
| // Case-insensitive: Windows NTFS and macOS HFS+ resolve case-variant | ||||||||||||||||||
| // filenames as the same file, and pre-existing custom filters may use | ||||||||||||||||||
| // .PHP / .Php. strcasecmp lets those continue to load on case-sensitive | ||||||||||||||||||
| // filesystems too. | ||||||||||||||||||
| if (0 !== strcasecmp(substr($file, -4), '.php')) { | ||||||||||||||||||
| continue; | ||||||||||||||||||
| } | ||||||||||||||||||
| // Resolve the real path and ensure it stays inside filters_enabled. | ||||||||||||||||||
| // Blocks symlinks pointing outside the directory and any crafted name | ||||||||||||||||||
| // whose canonical path escapes the base. | ||||||||||||||||||
| $realPath = realpath($this->filters_base . '/' . $file); | ||||||||||||||||||
| if (false === $realPath | ||||||||||||||||||
| || !str_starts_with($realPath, $baseReal . DIRECTORY_SEPARATOR)) { | ||||||||||||||||||
| continue; | ||||||||||||||||||
| } | ||||||||||||||||||
|
||||||||||||||||||
| } | |
| } | |
| // Only include regular readable files. This avoids runtime warnings | |
| // when a matching entry is a directory or otherwise unreadable. | |
| if (!is_file($realPath) || !is_readable($realPath)) { | |
| trigger_error('Unable to load Protector filter: ' . basename($realPath), E_USER_WARNING); | |
| continue; | |
| } |
Uh oh!
There was an error while loading. Please reload this page.