fix(thold): correct trigger_cmd variable references for low/normal states#765
fix(thold): correct trigger_cmd variable references for low/normal states#765somethingwithproof wants to merge 2 commits intoCacti:developfrom
Conversation
Wrap all get_request_var('rfilter') values with db_qstr() in RLIKE
SQL clauses across thold.php, thold_graph.php, and notify_lists.php.
10 sites total.
RLIKE accepts regex from rfilter which passes FILTER_VALIDATE_IS_REGEX
but is not SQL-safe. A single quote breaks the SQL string context.
Closes Cacti#761, Cacti#763
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
…ates thold_set_environ() for the breach_down path used trigger_cmd_high instead of trigger_cmd_low, and the breach_norm path also used trigger_cmd_high instead of trigger_cmd_norm. This caused low and normal threshold trigger commands to receive the high threshold command's environment variables. Closes Cacti#760 Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to fix incorrect trigger-command environment handling in thold_command_execution() and also hardens several RLIKE SQL filters against injection by quoting/preparing the rfilter input.
Changes:
- Update
thold_command_execution()to passtrigger_cmd_low/trigger_cmd_normintothold_set_environ()for breach-down and breach-normal paths. - Quote
rfiltervalues in multipleRLIKESQL fragments usingdb_qstr(). - Convert some notification list queries to prepared statements (
db_fetch_*_prepared) withRLIKE ?placeholders.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
thold.php |
Quotes rfilter in RLIKE filter to reduce SQL injection risk. |
thold_graph.php |
Quotes rfilter in multiple RLIKE filters (thresholds, hosts, log views/exports). |
thold_functions.php |
Changes which trigger command string is passed to thold_set_environ() for low/normal paths. |
notify_lists.php |
Quotes rfilter in a RLIKE filter; switches some list/template queries to prepared statements. |
| } elseif ($breach_down && $thold_data['trigger_cmd_low'] != '') { | ||
| $cmd = thold_replace_threshold_tags($thold_data['trigger_cmd_low'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name); | ||
| $cmd = thold_expand_string($thold_data, $cmd); | ||
|
|
||
| $environment = thold_set_environ($thold_data['trigger_cmd_high'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name); | ||
| $environment = thold_set_environ($thold_data['trigger_cmd_low'], $thold_data, $h, $thold_data['lastread'], $thold_data['local_graph_id'], $data_source_name); | ||
|
|
There was a problem hiding this comment.
thold_set_environ() currently does not reference its $text argument (it sets a fixed set of THOLD_* vars), so switching the call sites from trigger_cmd_high to trigger_cmd_low/trigger_cmd_norm does not change the generated environment. If the intent is for the environment to be derived from the specific trigger command, the logic needs to be implemented inside thold_set_environ() (or the unused parameter removed and the PR/issue description adjusted accordingly).
|
|
||
| if (get_request_var('rfilter') != '') { | ||
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE '" . get_request_var('rfilter') . "'"; | ||
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')) . ""; |
There was a problem hiding this comment.
This concatenation ends with . "", which is a no-op and makes the SQL assembly harder to read. Consider removing the trailing empty-string concatenation.
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')) . ""; | |
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')); |
|
|
||
| if (get_request_var('rfilter') != '') { | ||
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE '" . get_request_var('rfilter') . "'"; | ||
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')) . ""; |
There was a problem hiding this comment.
This concatenation ends with . "", which is a no-op and makes the SQL assembly harder to read. Consider removing the trailing empty-string concatenation.
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . " td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')) . ""; | |
| $sql_where .= ($sql_where == '' ? '(' : ' AND ') . ' td.name_cache RLIKE ' . db_qstr(get_request_var('rfilter')); |
|
|
||
| if (get_request_var('rfilter') != '') { | ||
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE '" . get_request_var('rfilter') . "'"; | ||
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE " . db_qstr(get_request_var('rfilter')) . ""; |
There was a problem hiding this comment.
This concatenation ends with . "", which is a no-op and makes the SQL assembly harder to read. Consider removing the trailing empty-string concatenation.
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE " . db_qstr(get_request_var('rfilter')) . ""; | |
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE " . db_qstr(get_request_var('rfilter')); |
|
|
||
| if (get_request_var('rfilter') != '') { | ||
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE '" . get_request_var('rfilter') . "'"; | ||
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE " . db_qstr(get_request_var('rfilter')) . ""; |
There was a problem hiding this comment.
This concatenation ends with . "", which is a no-op and makes the SQL assembly harder to read. Consider removing the trailing empty-string concatenation.
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE " . db_qstr(get_request_var('rfilter')) . ""; | |
| $sql_where .= ($sql_where == '' ? '' : ' AND') . " tl.description RLIKE " . db_qstr(get_request_var('rfilter')); |
|
|
||
| if (strlen(get_request_var('rfilter'))) { | ||
| $sql_where .= (!strlen($sql_where) ? '' : ' AND ') . "td.name_cache RLIKE '" . get_request_var('rfilter') . "'"; | ||
| $sql_where .= (!strlen($sql_where) ? '' : ' AND ') . "td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')) . ""; |
There was a problem hiding this comment.
This concatenation ends with . "", which is a no-op and makes the SQL assembly harder to read. Consider removing the trailing empty-string concatenation.
| $sql_where .= (!strlen($sql_where) ? '' : ' AND ') . "td.name_cache RLIKE " . db_qstr(get_request_var('rfilter')) . ""; | |
| $sql_where .= (!strlen($sql_where) ? '' : ' AND ') . 'td.name_cache RLIKE ' . db_qstr(get_request_var('rfilter')); |
Summary
Fix trigger command environment variable bug where the breach_down and breach_norm code paths used trigger_cmd_high instead of trigger_cmd_low and trigger_cmd_norm respectively.
This caused low and normal threshold trigger commands to receive the high threshold command's environment variables, producing incorrect command execution context.
Test plan
Closes #760