diff --git a/audit.php b/audit.php index dffed41..02d4c47 100644 --- a/audit.php +++ b/audit.php @@ -24,6 +24,7 @@ chdir('../../'); include_once('./include/auth.php'); +require_once(__DIR__ . '/audit_helpers.php'); set_default_action(); @@ -51,13 +52,13 @@ if ($data['action'] == 'cli') { $width = 'wide'; $output .= '
'; - $output .= '' . __('Page:', 'audit') . ' ' . $data['page'] . ''; - $output .= '
' . __('User:', 'audit') . ' ' . $data['user_agent'] . ''; - $output .= '
' . __('IP Address:', 'audit') . ' ' . $data['ip_address'] . ''; - $output .= '
' . __('Date:', 'audit') . ' ' . $data['event_time'] . ''; - $output .= '
' . __('Action:', 'audit') . ' ' . $data['action'] . ''; + $output .= '' . __('Page:', 'audit') . ' ' . html_escape($data['page']) . ''; + $output .= '
' . __('User:', 'audit') . ' ' . html_escape($data['user_agent']) . ''; + $output .= '
' . __('IP Address:', 'audit') . ' ' . html_escape($data['ip_address']) . ''; + $output .= '
' . __('Date:', 'audit') . ' ' . html_escape($data['event_time']) . ''; + $output .= '
' . __('Action:', 'audit') . ' ' . html_escape($data['action']) . ''; $output .= '
'; - $output .= '' . __('Script:', 'audit') . ' ' . $data['post'] . ''; + $output .= '' . __('Script:', 'audit') . ' ' . html_escape($data['post']) . ''; } elseif (cacti_sizeof($data)) { $attribs = json_decode($data['post']); @@ -74,11 +75,11 @@ } $output .= '
'; - $output .= '' . __('Page:', 'audit') . ' ' . $data['page'] . ''; - $output .= '
' . __('User:', 'audit') . ' ' . get_username($data['user_id']) . ''; - $output .= '
' . __('IP Address:', 'audit') . ' ' . $data['ip_address'] . ''; - $output .= '
' . __('Date:', 'audit') . ' ' . $data['event_time'] . ''; - $output .= '
' . __('Action:', 'audit') . ' ' . $data['action'] . ''; + $output .= '' . __('Page:', 'audit') . ' ' . html_escape($data['page']) . ''; + $output .= '
' . __('User:', 'audit') . ' ' . html_escape(get_username($data['user_id'])) . ''; + $output .= '
' . __('IP Address:', 'audit') . ' ' . html_escape($data['ip_address']) . ''; + $output .= '
' . __('Date:', 'audit') . ' ' . html_escape($data['event_time']) . ''; + $output .= '
' . __('Action:', 'audit') . ' ' . html_escape($data['action']) . ''; $output .= '
'; $output .= ''; @@ -98,9 +99,9 @@ } if (is_array($content)) { - $output .= '' . implode(',', $content) . ''; + $output .= ''; } else { - $output .= ''; + $output .= ''; } $i++; @@ -119,7 +120,7 @@ $output .= ''; foreach ($recordData as $record) { - $output .= ''; + $output .= ''; } } else { $output .= '
' . $field . '' . audit_html_escape($field) . '' . audit_html_escape(implode(',', $content)) . '' . $field . '' . $content . '' . audit_html_escape($field) . '' . audit_html_escape($content) . '
' . __('Record Data:', 'audit') . '
' . json_encode($record, JSON_PRETTY_PRINT) . '
' . audit_html_escape(json_encode($record, JSON_PRETTY_PRINT)) . '
'; @@ -163,8 +164,9 @@ function audit_export_rows() { $sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . ' page = ' . db_qstr(get_request_var('event_page')); } - if (!isempty_request_var('user_id') && get_request_var('user_id') > '-1') { - $sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . ' user_id = ' . get_request_var('user_id'); + $user_id = audit_normalize_int(get_request_var('user_id'), -1); + if ($user_id > -1) { + $sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . ' user_id = ' . $user_id; } $events = db_fetch_assoc("SELECT audit_log.*, user_auth.username @@ -357,8 +359,9 @@ function audit_log() { $sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . ' page = ' . db_qstr(get_request_var('event_page')); } - if (!isempty_request_var('user_id') && get_request_var('user_id') > '-1') { - $sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . ' user_id = ' . get_request_var('user_id'); + $user_id = audit_normalize_int(get_request_var('user_id'), -1); + if ($user_id > -1) { + $sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . ' user_id = ' . $user_id; } $total_rows = db_fetch_cell("SELECT @@ -463,4 +466,3 @@ function audit_log() { 0) { - db_execute('DELETE FROM audit_log WHERE event_time < FROM_UNIXTIME(' . (time() - ($retention * 86400)) . ')'); + db_execute_prepared('DELETE FROM audit_log WHERE event_time < FROM_UNIXTIME(?)', array(time() - ($retention * 86400))); $rows = db_affected_rows(); cacti_log('NOTE: Purged ' . $rows . ' Audit Log Records from Cacti', false, 'POLLER'); } diff --git a/tests/Integration/test_detail_render_escaping.php b/tests/Integration/test_detail_render_escaping.php new file mode 100644 index 0000000..06181b8 --- /dev/null +++ b/tests/Integration/test_detail_render_escaping.php @@ -0,0 +1,45 @@ +'); +$rendered_json = audit_html_escape(json_encode(array('payload' => ''))); + +assert_true( + 'field names are escaped before rendering', + strpos($rendered_field, ' 0 ? 1 : 0); diff --git a/tests/Unit/test_security_helpers.php b/tests/Unit/test_security_helpers.php new file mode 100644 index 0000000..6fb5f3c --- /dev/null +++ b/tests/Unit/test_security_helpers.php @@ -0,0 +1,47 @@ +alert(1)') === '<script>alert(1)</script>' +); + +echo "\n"; +echo "Results: $pass passed, $fail failed\n"; + +exit($fail > 0 ? 1 : 0); diff --git a/tests/e2e/test_security_wiring.php b/tests/e2e/test_security_wiring.php new file mode 100644 index 0000000..ddb88cd --- /dev/null +++ b/tests/e2e/test_security_wiring.php @@ -0,0 +1,48 @@ + 0 ? 1 : 0);