Skip to content

Commit da6d22e

Browse files
fix(security): comprehensive bug and security cleanup
- CRITICAL: prevent syslog_reports table DROP on upgrade (#300) - HIGH: parameterize domain stripping SQL (#261) - HIGH: wrap RLIKE filter values with db_qstr in syslog.php - MEDIUM: add CSV formula injection protection in exports (#256) - MEDIUM: sanitize DOM insertions with DOMPurify - LOW: parameterize admin CRUD delete/enable/disable (#252) - LOW: fix DST partition boundary using strtotime (#199) Closes #199, #252, #256, #259, #260, #261, #300 Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
1 parent 834a536 commit da6d22e

7 files changed

Lines changed: 55 additions & 30 deletions

File tree

functions.php

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ function syslog_partition_create($table) {
307307
/* determine the format of the table name */
308308
$time = time();
309309
$cformat = 'd' . date('Ymd', $time);
310-
$lnow = date('Y-m-d', $time+86400);
310+
$lnow = date('Y-m-d', strtotime('+1 day', $time));
311311

312312
$exists = syslog_db_fetch_row_prepared("SELECT *
313313
FROM `information_schema`.`partitions`
@@ -788,12 +788,12 @@ function syslog_export($tab) {
788788

789789
print
790790
'"' .
791-
$host . '","' .
792-
ucfirst($facility) . '","' .
793-
ucfirst($priority) . '","' .
794-
ucfirst($program) . '","' .
795-
$message['logtime'] . '","' .
796-
$message[$syslog_incoming_config['textField']] . '"' . "\r\n";
791+
syslog_csv_safe($host) . '","' .
792+
syslog_csv_safe(ucfirst($facility)) . '","' .
793+
syslog_csv_safe(ucfirst($priority)) . '","' .
794+
syslog_csv_safe(ucfirst($program)) . '","' .
795+
syslog_csv_safe($message['logtime']) . '","' .
796+
syslog_csv_safe($message[$syslog_incoming_config['textField']]) . '"' . "\r\n";
797797
}
798798
}
799799
} else {
@@ -815,14 +815,14 @@ function syslog_export($tab) {
815815

816816
print
817817
'"' .
818-
$message['name'] . '","' .
819-
$severity . '","' .
820-
$message['logtime'] . '","' .
821-
$message['logmsg'] . '","' .
822-
$message['host'] . '","' .
823-
ucfirst($message['facility']) . '","' .
824-
ucfirst($message['priority']) . '","' .
825-
$message['count'] . '"' . "\r\n";
818+
syslog_csv_safe($message['name']) . '","' .
819+
syslog_csv_safe($severity) . '","' .
820+
syslog_csv_safe($message['logtime']) . '","' .
821+
syslog_csv_safe($message['logmsg']) . '","' .
822+
syslog_csv_safe($message['host']) . '","' .
823+
syslog_csv_safe(ucfirst($message['facility'])) . '","' .
824+
syslog_csv_safe(ucfirst($message['priority'])) . '","' .
825+
syslog_csv_safe($message['count']) . '"' . "\r\n";
826826
}
827827
}
828828
}
@@ -2050,6 +2050,31 @@ function syslog_postprocess_tables() {
20502050
}
20512051
}
20522052

2053+
/**
2054+
* syslog_csv_safe - Escapes a value for safe inclusion in a CSV field.
2055+
*
2056+
* Prevents formula injection by prefixing cells that start with a trigger
2057+
* character, and escapes embedded double-quotes per RFC 4180.
2058+
*
2059+
* @param (mixed) $value The value to sanitize
2060+
*
2061+
* @return (string) The sanitized string
2062+
*/
2063+
function syslog_csv_safe($value) {
2064+
if ($value === null || $value === '') {
2065+
return '';
2066+
}
2067+
2068+
$value = (string) $value;
2069+
$value = str_replace('"', '""', $value);
2070+
2071+
if (preg_match('/^[=+\-@\t\r]/', $value)) {
2072+
$value = "'" . $value;
2073+
}
2074+
2075+
return $value;
2076+
}
2077+
20532078
/**
20542079
* syslog_process_reports - Processes all syslog reports scheduled to run
20552080
*

js/functions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ function initSyslogMain(config) {
227227

228228
$.each(data, function(index, hostData) {
229229
if ($('#host option[value="'+index+'"]').length == 0) {
230-
$('#host').append('<option class="'+hostData.class+'" value="'+index+'">'+hostData.host+'</option>');
230+
$('#host').append('<option class="'+DOMPurify.sanitize(hostData.class)+'" value="'+DOMPurify.sanitize(index)+'">'+DOMPurify.sanitize(hostData.host)+'</option>');
231231
}
232232
});
233233

setup.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ function syslog_setup_table_new($options) {
626626
$newreport = true;
627627
}
628628

629-
if ($truncate || !$newreport) {
629+
if ($truncate) {
630630
syslog_db_execute("DROP TABLE IF EXISTS `" . $syslogdb_default . "`.`syslog_reports`");
631631
}
632632

syslog.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,8 @@ function get_stats_records(&$sql_where, &$sql_groupby, $rows) {
393393
/* form the 'where' clause for our main sql query */
394394
if (!isempty_request_var('rfilter')) {
395395
$sql_where .= ($sql_where == '' ? 'WHERE ' : ' AND ') .
396-
"sh.host RLIKE '" . get_request_var('rfilter') . "'
397-
OR spr.program RLIKE '" . get_request_var('rfilter') . "'";
396+
"sh.host RLIKE " . db_qstr(get_request_var('rfilter')) . "
397+
OR spr.program RLIKE " . db_qstr(get_request_var('rfilter'));
398398
}
399399

400400
if (get_request_var('host') == '-2') {
@@ -910,9 +910,9 @@ function get_syslog_messages(&$sql_where, $rows, $tab) {
910910

911911
if (!isempty_request_var('rfilter')) {
912912
if ($tab == 'syslog') {
913-
$sql_where .= ($sql_where == '' ? 'WHERE ' : ' AND ') . "message RLIKE '" . get_request_var('rfilter') . "'";
913+
$sql_where .= ($sql_where == '' ? 'WHERE ' : ' AND ') . "message RLIKE " . db_qstr(get_request_var('rfilter'));
914914
} else {
915-
$sql_where .= ($sql_where == '' ? 'WHERE ' : ' AND ') . "logmsg RLIKE '" . get_request_var('rfilter') . "'";
915+
$sql_where .= ($sql_where == '' ? 'WHERE ' : ' AND ') . "logmsg RLIKE " . db_qstr(get_request_var('rfilter'));
916916
}
917917
}
918918

syslog_alerts.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,17 +321,17 @@ function api_syslog_alert_save($id, $name, $method, $level, $num, $type, $messag
321321

322322
function api_syslog_alert_remove($id) {
323323
global $syslogdb_default;
324-
syslog_db_execute("DELETE FROM `" . $syslogdb_default . "`.`syslog_alert` WHERE id='" . $id . "'");
324+
syslog_db_execute_prepared("DELETE FROM `" . $syslogdb_default . "`.`syslog_alert` WHERE id = ?", array(intval($id)));
325325
}
326326

327327
function api_syslog_alert_disable($id) {
328328
global $syslogdb_default;
329-
syslog_db_execute("UPDATE `" . $syslogdb_default . "`.`syslog_alert` SET enabled='' WHERE id='" . $id . "'");
329+
syslog_db_execute_prepared("UPDATE `" . $syslogdb_default . "`.`syslog_alert` SET enabled='' WHERE id = ?", array(intval($id)));
330330
}
331331

332332
function api_syslog_alert_enable($id) {
333333
global $syslogdb_default;
334-
syslog_db_execute("UPDATE `" . $syslogdb_default . "`.`syslog_alert` SET enabled='on' WHERE id='" . $id . "'");
334+
syslog_db_execute_prepared("UPDATE `" . $syslogdb_default . "`.`syslog_alert` SET enabled='on' WHERE id = ?", array(intval($id)));
335335
}
336336

337337
/* ---------------------

syslog_removal.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,17 +306,17 @@ function api_syslog_removal_save($id, $name, $type, $message, $rmethod, $notes,
306306

307307
function api_syslog_removal_remove($id) {
308308
global $syslogdb_default;
309-
syslog_db_execute("DELETE FROM `" . $syslogdb_default . "`.`syslog_remove` WHERE id='" . $id . "'");
309+
syslog_db_execute_prepared("DELETE FROM `" . $syslogdb_default . "`.`syslog_remove` WHERE id = ?", array(intval($id)));
310310
}
311311

312312
function api_syslog_removal_disable($id) {
313313
global $syslogdb_default;
314-
syslog_db_execute("UPDATE `" . $syslogdb_default . "`.`syslog_remove` SET enabled='' WHERE id='" . $id . "'");
314+
syslog_db_execute_prepared("UPDATE `" . $syslogdb_default . "`.`syslog_remove` SET enabled='' WHERE id = ?", array(intval($id)));
315315
}
316316

317317
function api_syslog_removal_enable($id) {
318318
global $syslogdb_default;
319-
syslog_db_execute("UPDATE `" . $syslogdb_default . "`.`syslog_remove` SET enabled='on' WHERE id='" . $id . "'");
319+
syslog_db_execute_prepared("UPDATE `" . $syslogdb_default . "`.`syslog_remove` SET enabled='on' WHERE id = ?", array(intval($id)));
320320
}
321321

322322
function api_syslog_removal_reprocess($id) {

syslog_reports.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,17 @@ function api_syslog_report_save($id, $name, $type, $message, $timespan, $timepar
315315

316316
function api_syslog_report_remove($id) {
317317
global $syslogdb_default;
318-
syslog_db_execute('DELETE FROM `' . $syslogdb_default . '`.`syslog_reports` WHERE id=' . $id);
318+
syslog_db_execute_prepared('DELETE FROM `' . $syslogdb_default . '`.`syslog_reports` WHERE id = ?', array(intval($id)));
319319
}
320320

321321
function api_syslog_report_disable($id) {
322322
global $syslogdb_default;
323-
syslog_db_execute('UPDATE `' . $syslogdb_default . "`.`syslog_reports` SET enabled='' WHERE id=" . $id);
323+
syslog_db_execute_prepared('UPDATE `' . $syslogdb_default . "`.`syslog_reports` SET enabled='' WHERE id = ?", array(intval($id)));
324324
}
325325

326326
function api_syslog_report_enable($id) {
327327
global $syslogdb_default;
328-
syslog_db_execute('UPDATE `' . $syslogdb_default . "`.`syslog_reports` SET enabled='on' WHERE id=" . $id);
328+
syslog_db_execute_prepared('UPDATE `' . $syslogdb_default . "`.`syslog_reports` SET enabled='on' WHERE id = ?", array(intval($id)));
329329
}
330330

331331
/* ---------------------

0 commit comments

Comments
 (0)