Skip to content

Commit 260bccd

Browse files
fix(security): refine partition and timestamp boundary handling
1 parent aff9552 commit 260bccd

1 file changed

Lines changed: 22 additions & 10 deletions

File tree

functions.php

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,20 @@ function syslog_partition_create($table, $time = null) {
300300
return false;
301301
}
302302

303+
if (!preg_match('/^[a-zA-Z0-9_]+$/', $syslogdb_default)) {
304+
cacti_log("SYSLOG ERROR: Invalid database name; partition create aborted", false, 'SYSLOG');
305+
306+
return false;
307+
}
308+
303309
if ($time === null) {
304310
$time = time() + 3600;
305311
}
306312

307-
// Reject non-numeric or pre-epoch timestamps; boundary math assumes a
308-
// non-negative UTC epoch so negative or bogus inputs cannot underflow
309-
// the (int)($time / 86400) + 1 computation below.
310-
if (!is_numeric($time) || (int)$time < 0) {
313+
// Reject non-numeric, negative, or far-future timestamps; boundary
314+
// math assumes a non-negative UTC epoch within 64-bit safe range so
315+
// extreme inputs cannot underflow or overflow to float.
316+
if (!is_numeric($time) || (int)$time < 0 || (int)$time > 4102444800) {
311317
cacti_log("SYSLOG ERROR: syslog_partition_create called with invalid time '$time' for table '$table'", false, 'SYSLOG');
312318

313319
return false;
@@ -386,7 +392,7 @@ function syslog_partition_create($table, $time = null) {
386392
* derive from integer arithmetic and gmdate(), so they contain
387393
* only digits, hyphens, and the letter 'd'.
388394
*/
389-
$create_syntax = syslog_db_fetch_row("SHOW CREATE TABLE `$syslogdb_default`.`$table`");
395+
$create_syntax = syslog_db_fetch_row_prepared("SHOW CREATE TABLE `$syslogdb_default`.`$table`");
390396

391397
if (!cacti_sizeof($create_syntax) || empty($create_syntax['Create Table'])) {
392398
cacti_log("SYSLOG ERROR: SHOW CREATE TABLE returned no rows for '$table'; partition rotation aborted", false, 'SYSLOG');
@@ -397,11 +403,11 @@ function syslog_partition_create($table, $time = null) {
397403
$create_sql = $create_syntax['Create Table'];
398404

399405
if (stripos($create_sql, 'TO_DAYS') !== false) {
400-
syslog_db_execute("ALTER TABLE `$syslogdb_default`.`$table` REORGANIZE PARTITION dMaxValue INTO (
406+
syslog_db_execute_prepared("ALTER TABLE `$syslogdb_default`.`$table` REORGANIZE PARTITION dMaxValue INTO (
401407
PARTITION $cformat VALUES LESS THAN (TO_DAYS('$boundary_date')),
402408
PARTITION dMaxValue VALUES LESS THAN MAXVALUE)");
403409
} elseif (stripos($create_sql, 'UNIX_TIMESTAMP') !== false) {
404-
syslog_db_execute("ALTER TABLE `$syslogdb_default`.`$table` REORGANIZE PARTITION dMaxValue INTO (
410+
syslog_db_execute_prepared("ALTER TABLE `$syslogdb_default`.`$table` REORGANIZE PARTITION dMaxValue INTO (
405411
PARTITION $cformat VALUES LESS THAN ($boundary_epoch),
406412
PARTITION dMaxValue VALUES LESS THAN MAXVALUE)");
407413
} else {
@@ -433,6 +439,12 @@ function syslog_partition_remove($table) {
433439
return 0;
434440
}
435441

442+
if (!preg_match('/^[a-zA-Z0-9_]+$/', $syslogdb_default)) {
443+
cacti_log("SYSLOG ERROR: Invalid database name; partition remove aborted", false, 'SYSLOG');
444+
445+
return 0;
446+
}
447+
436448
$lock_name = substr(hash('sha256', $syslogdb_default . '.syslog_partition_remove.' . $table), 0, 60);
437449

438450
$locked = syslog_db_fetch_cell_prepared('SELECT GET_LOCK(?, 10)', [$lock_name]);
@@ -482,11 +494,11 @@ function syslog_partition_remove($table) {
482494

483495
syslog_debug("Removing partition '" . $part_name . "'");
484496

485-
/* $table passed syslog_partition_table_allowed() at function entry; $part_name is regex-validated above. */
486-
$result = syslog_db_execute("ALTER TABLE `$syslogdb_default`.`$table` DROP PARTITION `$part_name`");
497+
/* $table passed syslog_partition_table_allowed() at function entry; $part_name is regex-validated above. DDL identifiers cannot be parameterized. */
498+
$result = syslog_db_execute_prepared("ALTER TABLE `$syslogdb_default`.`$table` DROP PARTITION `$part_name`");
487499

488500
if ($result === false) {
489-
cacti_log("SYSLOG ERROR: Failed to drop partition '$part_name' from '$table'; aborting further drops", false, 'SYSLOG');
501+
cacti_log("SYSLOG ERROR: Failed to drop partition '$part_name' from '$table' after $i successful drop(s); aborting further drops", false, 'SYSLOG');
490502
break;
491503
}
492504

0 commit comments

Comments
 (0)