View Issue Details

IDProjectCategoryView StatusLast Update
5339Composrsecurityloggingpublic2023-02-21 02:06
ReporterChris Graham Assigned ToGuest  
PrioritynormalSeverityfeature 
Status newResolutionopen 
Summary5339: Summary of security incidents in past 24 hours
DescriptionWhen a site is under heavy attack, e.g. by a bot, it would be helpful to have a clear summary of what is happening, rather than a long pagination of individual events.

I have a patch for this, which is attached. It would need a little polishing.
TagsHas Patch, Roadmap: Over the horizon
Attach Tags
Attached Files
security-summaries.patch (5,700 bytes)   
From 798de864b075aae7055b6a20a53260f7eada5e0f Mon Sep 17 00:00:00 2001
From: Chris Graham <[email protected]>
Date: Wed, 21 Dec 2022 08:10:43 -0600
Subject: [PATCH] Added security summaries to admin_security

---
 adminzone/pages/modules/admin_security.php   | 44 +++++++++++++++++++-
 themes/default/templates/SECURITY_SCREEN.tpl | 24 +++++++++++
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/adminzone/pages/modules/admin_security.php b/adminzone/pages/modules/admin_security.php
index 39d653729..8b3b64646 100644
--- a/adminzone/pages/modules/admin_security.php
+++ b/adminzone/pages/modules/admin_security.php
@@ -183,6 +183,8 @@ class Module_admin_security
      */
     public function security_interface()
     {
+        $filter_to_ip = get_param_string('filter_to_ip', null);
+
         // Failed logins
         $start = get_param_integer('failed_start', 0);
         $max = get_param_integer('failed_max', 50);
@@ -198,7 +200,10 @@ class Module_admin_security
         require_code('templates_results_table');
         $fields_title = results_field_title(array(do_lang_tempcode('USERNAME'), do_lang_tempcode('DATE_TIME'), do_lang_tempcode('IP_ADDRESS')), $sortables, 'failed_sort', $_sortable . ' ' . $sort_order);
         $member_id = post_param_integer('member_id', null);
-        $map = (!is_null($member_id)) ? array('failed_account' => $GLOBALS['FORUM_DRIVER']->get_username($member_id)) : null;
+        $map = (!is_null($member_id)) ? array('failed_account' => $GLOBALS['FORUM_DRIVER']->get_username($member_id)) : array();
+        if ($filter_to_ip !== null) {
+            $map['ip'] = $filter_to_ip;
+        }
         $max_rows = $GLOBALS['SITE_DB']->query_select_value('failedlogins', 'COUNT(*)', $map);
         $rows = $GLOBALS['SITE_DB']->query_select('failedlogins', array('*'), $map, 'ORDER BY ' . $_sortable . ' ' . $sort_order, $max, $start);
         $fields = new Tempcode();
@@ -210,9 +215,42 @@ class Module_admin_security
         $failed_logins = results_table(do_lang_tempcode('FAILED_LOGINS'), $start, 'failed_start', $max, 'failed_max', $max_rows, $fields_title, $fields, $sortables, $_sortable, $sort_order, 'failed_sort', new Tempcode());
 
         $member_id = post_param_integer('member_id', null);
-        $map = (!is_null($member_id)) ? array('member_id' => $member_id) : null;
+        $map = (!is_null($member_id)) ? array('member_id' => $member_id) : array();
+        if ($filter_to_ip !== null) {
+            $map['ip'] = $filter_to_ip;
+        }
         list($alerts, $num_alerts) = find_security_alerts($map);
 
+        // Summaries
+        $failed_login_summary = array();
+        $alert_summary = array();
+        if ($filter_to_ip === null) {
+            $summary_max = 10;
+            $summary_hours = 24;
+
+            // Failed logins summary
+            $rows = $GLOBALS['SITE_DB']->query_select('failedlogins', array('ip', 'COUNT(*) AS cnt'), array(), 'WHERE date_and_time>' . strval(time() - 60 * 60 * $summary_hours) . ' GROUP BY ip ORDER BY COUNT(*) DESC', $summary_max);
+            foreach ($rows as $row) {
+                $failed_login_summary[] = array(
+                    'IP_ADDRESS' => $row['ip'],
+                    'COUNT' => integer_format($row['cnt']),
+                    '_COUNT' => strval($row['cnt']),
+                    'FILTER_URL' => get_self_url(false, false, array('filter_to_ip' => $row['ip'])),
+                );
+            }
+
+            // Security alerts summary
+            $rows = $GLOBALS['SITE_DB']->query_select('hackattack', array('ip', 'COUNT(*) AS cnt'), array(), 'WHERE date_and_time>' . strval(time() - 60 * 60 * $summary_hours) . ' GROUP BY ip ORDER BY COUNT(*) DESC', $summary_max);
+            foreach ($rows as $row) {
+                $alert_summary[] = array(
+                    'IP_ADDRESS' => $row['ip'],
+                    'COUNT' => integer_format($row['cnt']),
+                    '_COUNT' => strval($row['cnt']),
+                    'FILTER_URL' => get_self_url(false, false, array('filter_to_ip' => $row['ip'])),
+                );
+            }
+        }
+
         $post_url = build_url(array('page' => '_SELF', 'type' => 'clean', 'start' => $start, 'max' => $max), '_SELF');
 
         $tpl = do_template('SECURITY_SCREEN', array(
@@ -223,6 +261,8 @@ class Module_admin_security
             'ALERTS' => $alerts,
             'NUM_ALERTS' => strval($num_alerts),
             'URL' => $post_url,
+            'FAILED_LOGIN_SUMMARY' => $failed_login_summary,
+            'ALERT_SUMMARY' => $alert_summary,
         ));
 
         require_code('templates_internalise_screen');
diff --git a/themes/default/templates/SECURITY_SCREEN.tpl b/themes/default/templates/SECURITY_SCREEN.tpl
index b4c67b4a2..54e74a689 100644
--- a/themes/default/templates/SECURITY_SCREEN.tpl
+++ b/themes/default/templates/SECURITY_SCREEN.tpl
@@ -2,6 +2,18 @@
 
 <h2>{!FAILED_LOGINS}</h2>
 
+{+START,IF_NON_EMPTY,{FAILED_LOGIN_SUMMARY}}
+	<p>Top 10 suspicious IPs in past 24 hours&hellip;</p>
+
+	<ul>
+		{+START,LOOP,FAILED_LOGIN_SUMMARY}
+			<li><a href="{FILTER_URL*}">{IP_ADDRESS*}</a> <span class="associated_details">({COUNT*})</span></li>
+		{+END}
+	</ul>
+
+	<p>Full table&hellip;</p>
+{+END}
+
 {FAILED_LOGINS}
 
 <h2>{!SECURITY_ALERTS}</h2>
@@ -12,6 +24,18 @@
 	</p>
 {+END}
 
+{+START,IF_NON_EMPTY,{ALERT_SUMMARY}}
+	<p>Top 10 suspicious IPs in past 24 hours&hellip;</p>
+
+	<ul>
+		{+START,LOOP,ALERT_SUMMARY}
+			<li><a href="{FILTER_URL*}">{IP_ADDRESS*}</a> <span class="associated_details">({COUNT*})</span></li>
+		{+END}
+	</ul>
+
+	<p>Full table&hellip;</p>
+{+END}
+
 {ALERTS}
 
 {+START,IF,{$NEQ,{NUM_ALERTS},0}}
-- 
GitLab

security-summaries.patch (5,700 bytes)   
Time estimation (hours)1
Sponsorship open

Sponsor

Date Added Member Amount Sponsored

Activities

Add Note

View Status
Note
Upload Files
Maximum size: 32,768 KiB

Attach files by dragging & dropping, selecting or pasting them.
You are not logged in You are not logged in. This means you will not get any e-mail notifications. And if you reply, we will not know for sure you are the original poster of the issue.

Issue History

Date Modified Username Field Change
2023-02-21 02:06 Chris Graham New Issue
2023-02-21 02:06 Chris Graham Tag Attached: Has Patch
2023-02-21 02:06 Chris Graham Tag Attached: Roadmap: v12
2023-02-21 02:06 Chris Graham File Added: security-summaries.patch
2024-03-26 00:58 PDStig Tag Renamed Roadmap: v12 => Roadmap: Over the horizon