Skip to content

Commit 6807d6b

Browse files
fix: replace open-redirect blocklist with allowlist in syslog_get_import_xml_payload
Backslash-prefixed inputs (\evil.com, /\evil.com) and percent-encoded schemes (%5cevil.com) bypassed the previous blocklist regex even after urldecode(). The allowlist accepts only relative paths beginning with a filename character — schemes, protocol-relative URLs, and backslash prefixes all fail to match and collapse to index.php.
1 parent beced7b commit 6807d6b

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

functions.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,10 @@ function syslog_apply_selected_items_action($selected_items, $drp_action, $actio
182182
}
183183

184184
function syslog_get_import_xml_payload($redirect_url) {
185-
/* Reject non-relative redirect targets to prevent open redirect.
186-
All legitimate callers pass a relative path (e.g. syslog_removal.php?header=false). */
187-
if (preg_match('/^(?:[a-z][a-z\d+\-.]*:|\/{2})/i', $redirect_url)) {
185+
/* Allow only relative paths that start with a filename character. Schemes
186+
(http://), protocol-relative URLs (//), and backslash prefixes (\, /\)
187+
all fail to match the allowlist and collapse to the safe default. */
188+
if (!preg_match('/^[a-zA-Z0-9_\-][a-zA-Z0-9_\-\.\/]*(?:\?[a-zA-Z0-9_\-&=%\.+]*)?$/', $redirect_url)) {
188189
$redirect_url = 'index.php';
189190
}
190191

@@ -424,16 +425,18 @@ function syslog_partition_remove($table) {
424425
$user_partitions = sizeof($number_of_partitions) - 1;
425426
if ($user_partitions >= $days) {
426427
$i = 0;
427-
while ($user_partitions > $days) {
428+
while ($user_partitions > $days && $i < cacti_sizeof($number_of_partitions)) {
428429
$oldest = $number_of_partitions[$i];
429430

430431
/* PARTITION_NAME comes from information_schema, but validate the
431432
format before DDL interpolation — MySQL does not support parameter
432433
binding for DDL statements. */
433434
if (!preg_match('/^d\d{8}$/', $oldest['PARTITION_NAME'])) {
434-
cacti_log("SYSLOG ERROR: Unexpected partition name format '" . $oldest['PARTITION_NAME'] . "' for table '$table', skipping", false, 'SYSTEM');
435+
cacti_log("SYSLOG ERROR: Unexpected partition name format '" . $oldest['PARTITION_NAME'] . "' for table '$table', skipping, cannot prune past this entry", false, 'SYSTEM');
435436
$i++;
436-
$user_partitions--;
437+
/* Do NOT decrement $user_partitions: no partition was dropped,
438+
so the actual count is unchanged. The upper bound on $i
439+
prevents an infinite loop when all remaining names are invalid. */
437440
continue;
438441
}
439442

0 commit comments

Comments
 (0)