public inbox for development@lists.ipfire.org
 help / color / mirror / Atom feed
* [PATCH 1/4] ruleset-sources: Add details about rule sid and info URL
@ 2026-02-09 14:23 Stefan Schantl
  2026-02-09 14:23 ` [PATCH 2/4] ids-functions.pl: Add function to get the provider by a given rule id Stefan Schantl
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Stefan Schantl @ 2026-02-09 14:23 UTC (permalink / raw)
  To: development; +Cc: Stefan Schantl

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 config/suricata/ruleset-sources | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/config/suricata/ruleset-sources b/config/suricata/ruleset-sources
index af65648af..5b9073d85 100644
--- a/config/suricata/ruleset-sources
+++ b/config/suricata/ruleset-sources
@@ -13,6 +13,8 @@ package IDS::Ruleset;
 # 	requires_subscription => "True/False" - If some kind of registration code is required in order to download the ruleset.
 # 	dl_url => The download URL to grab the ruleset.
 # 	dl_type => "archive/plain" - To specify, if the downloaded file is a packed archive or a plain text file.
+# 	sid_range => The sid range which the provider uses for it's rules, specified as an array. "[start sid, stop sid]"
+# 	sid_info_url => An URL which provides additional information about a rule based on it's sid.
 # },
 
 # Hash which contains the supported ruleset providers.
@@ -25,6 +27,8 @@ our %Providers = (
 		requires_subscription => "True",
 		dl_url => "https://www.snort.org/rules/snortrules-snapshot-29200.tar.gz?oinkcode=<subscription_code>",
 		dl_type => "archive",
+		sid_range => ["1", "1000000"],
+		sid_info_url => "https://www.snort.org/rule_docs/1-<sid>",
 	},
 
 	# Ruleset for registered sourcefire users with a valid subscription.
@@ -35,6 +39,8 @@ our %Providers = (
 		requires_subscription => "True",
 		dl_url => "https://www.snort.org/rules/snortrules-snapshot-29200.tar.gz?oinkcode=<subscription_code>",
 		dl_type => "archive",
+		sid_range => ["1", "1000000"],
+		sid_info_url => "https://www.snort.org/rule_docs/1-<sid>",
 	},
 
 	# Community rules from sourcefire.
@@ -45,6 +51,8 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://www.snort.org/downloads/community/community-rules.tar.gz",
 		dl_type => "archive",
+		sid_range => ["1", "1000000"],
+		sid_info_url => "https://www.snort.org/rule_docs/1-<sid>",
 	},
 
 	# Emerging threats community rules.
@@ -55,6 +63,8 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://rules.emergingthreats.net/open/suricata-5.0/emerging.rules.tar.gz",
 		dl_type => "archive",
+		sid_range => ["2000000", "2999999"],
+		sid_info_url => "https://threatintel.proofpoint.com/sid/<sid>",
 	},
 
 	# Emerging threats Pro rules.
@@ -65,6 +75,8 @@ our %Providers = (
 		requires_subscription => "True",
 		dl_url => "https://rules.emergingthreatspro.com/<subscription_code>/suricata-5.0/etpro.rules.tar.gz",
 		dl_type => "archive",
+		sid_range => ["2000000", "2999999"],
+		sid_info_url => "https://threatintel.proofpoint.com/sid/<sid>",
 	},
 
 	# Abuse.ch SSLBL Blacklist rules.
@@ -72,6 +84,7 @@ our %Providers = (
 		summary => "Abuse.ch SSLBL Blacklist Rules",
 		website => "https://sslbl.abuse.ch/",
 		tr_string => "sslbl blacklist rules",
+		sid_range => ["902200000", "902299999"],
 	},
 
 	# Etnetera Aggressive Blacklist.
@@ -82,6 +95,7 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://security.etnetera.cz/feeds/etn_aggressive.rules",
 		dl_type => "plain",
+		sid_range => ["500000", "599999"],
 	},
 
 	# OISF Traffic ID rules.
@@ -92,6 +106,7 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://openinfosecfoundation.org/rules/trafficid/trafficid.rules",
 		dl_type => "plain",
+		sid_range => ["300000000", "301000000"],
 	},
 
 	# Positive Technologies Attack Detection Team rules.
@@ -99,6 +114,7 @@ our %Providers = (
 		summary => "PT Attack Detection Team Rules",
 		website => "https://github.com/ptresearch/AttackDetection",
 		tr_string => "attack detection team rules",
+		sid_range => ["10000000", "11999999"],
 	},
 
 	# Secureworks Security rules.
@@ -130,6 +146,7 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://threatfox.abuse.ch/downloads/threatfox_suricata.rules",
 		dl_type => "plain",
+		sid_range => ["91000000", "91999999"],
 	},
 
 	# Travis B. Green hunting rules.
@@ -140,6 +157,7 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://raw.githubusercontent.com/travisbgreen/hunting-rules/master/hunting.rules",
 		dl_type => "plain",
+		sid_range => ["2610000", "2619999"],
 	},
 
 	ipfire_dbl => {
@@ -149,5 +167,6 @@ our %Providers = (
 		requires_subscription => "False",
 		dl_url => "https://dbl.ipfire.org/lists/suricata.tar.gz",
 		dl_type => "archive",
+		sid_range => ["406000000", "406999999"],
 	},
 );
-- 
2.47.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/4] ids-functions.pl: Add function to get the provider by a given rule id
  2026-02-09 14:23 [PATCH 1/4] ruleset-sources: Add details about rule sid and info URL Stefan Schantl
@ 2026-02-09 14:23 ` Stefan Schantl
  2026-02-09 14:23 ` [PATCH 3/4] ids-functions.pl: Add function to get the info url for " Stefan Schantl
  2026-02-09 14:23 ` [PATCH 4/4] logs.cgi/ids.dat: Use new mechanic to obtain sid info url's Stefan Schantl
  2 siblings, 0 replies; 4+ messages in thread
From: Stefan Schantl @ 2026-02-09 14:23 UTC (permalink / raw)
  To: development; +Cc: Stefan Schantl

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 config/cfgroot/ids-functions.pl | 80 +++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/config/cfgroot/ids-functions.pl b/config/cfgroot/ids-functions.pl
index bede5fca0..0271ef4fc 100644
--- a/config/cfgroot/ids-functions.pl
+++ b/config/cfgroot/ids-functions.pl
@@ -1829,4 +1829,84 @@ sub generate_report_generator_config() {
 	close(FILE);
 }
 
+#
+## Function to get the provider handle by a given rule sid.
+#
+sub get_provider_by_sid ($) {
+	my ($sid) = @_;
+
+	# Get all known ruleset providers.
+	my @ruleset_providers = &get_ruleset_providers();
+
+	# Temporary hash to store found ranges.
+	my %tmphash = ();
+	my @tmparray;
+
+	# Loop through the array of known providers.
+	foreach my $provider (@ruleset_providers) {
+		# Skip provider if no sid range is specified.
+		next unless ($IDS::Ruleset::Providers{$provider}{"sid_range"});
+
+		# Grab and the dereference the sid range.
+		my @sid_range = @{ $IDS::Ruleset::Providers{$provider}{"sid_range"} };
+
+		# Check if the given sid is in the range of the current processed provider.
+		next unless (&is_sid_in_range($sid, \@sid_range));
+
+		# Assign some nice human-readable values.
+		my $start = $sid_range[0];
+		my $end = $sid_range[1];
+
+		# Calculate the sid range.
+		my $range = $end - $start;
+
+		# Assign the found provider and it's range to the temporary hash.
+		$tmphash{$range} = $provider;
+	}
+
+	# Sort the ranges of the found providers and store them in a temporary
+	# array - This is neccessary in case more than one range has been found.
+	@tmparray = sort (keys %tmphash);
+
+	# Return if nothing has been found.
+	return unless(@tmparray);
+
+	# The first element of the temporary array contains our smalles sid range
+	# which the given sid has to belong - grab the stored handle.
+	my $handle = $tmphash{$tmparray[0]};
+
+	# Return the obtained handle.
+	return $handle;
+}
+
+#
+## Function to check if a given single sid is in a given range.
+#
+sub is_sid_in_range($\@) {
+	my ($sid, $range_ref) = @_;
+
+	# Deref the array ref and assig to array.
+	my @range = @{ $range_ref };
+
+	# Assign some nice human-readable values.
+	my $range_start = $range[0];
+	my $range_stop = $range[1];
+
+	# Early exit in case the range has been passed the
+	# wrong way around.
+	return undef if ($range_start > $range_stop);
+
+	# Return if the given sid is lower than the start one.
+	return if ($sid < $range_start);
+
+	# Return if the given sid is higher than the max range.
+	return if ($sid > $range_stop);
+
+	# Return True if the given sid is lower or equals the max range.
+	return 1 if ($sid <= $range_stop);
+
+	# If we got here, something strange happend.
+	return undef;
+}
+
 1;
-- 
2.47.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/4] ids-functions.pl: Add function to get the info url for a given rule id
  2026-02-09 14:23 [PATCH 1/4] ruleset-sources: Add details about rule sid and info URL Stefan Schantl
  2026-02-09 14:23 ` [PATCH 2/4] ids-functions.pl: Add function to get the provider by a given rule id Stefan Schantl
@ 2026-02-09 14:23 ` Stefan Schantl
  2026-02-09 14:23 ` [PATCH 4/4] logs.cgi/ids.dat: Use new mechanic to obtain sid info url's Stefan Schantl
  2 siblings, 0 replies; 4+ messages in thread
From: Stefan Schantl @ 2026-02-09 14:23 UTC (permalink / raw)
  To: development; +Cc: Stefan Schantl

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 config/cfgroot/ids-functions.pl | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/config/cfgroot/ids-functions.pl b/config/cfgroot/ids-functions.pl
index 0271ef4fc..93d1acdee 100644
--- a/config/cfgroot/ids-functions.pl
+++ b/config/cfgroot/ids-functions.pl
@@ -1909,4 +1909,29 @@ sub is_sid_in_range($\@) {
 	return undef;
 }
 
+#
+## Function to get the sid info url in case it is defined
+#
+sub get_sid_info_url($) {
+	my ($sid) = @_;
+
+	# Call function to get the provider for this rule id.
+	my $provider = &get_provider_by_sid($sid);
+
+	# Exit if no provder could be determined.
+	return unless($provider);
+
+	# Exit if no info URL is known for the provider.
+	return unless($IDS::Ruleset::Providers{$provider}{"sid_info_url"});
+
+	# Grab the URL for the given provider.
+	my $info_url = $IDS::Ruleset::Providers{$provider}{"sid_info_url"};
+
+	# Replace the <sid> placeholder with the given sid.
+	$info_url =~ s/\<sid\>/$sid/g;
+
+	# Return the URL.
+	return $info_url;
+}
+
 1;
-- 
2.47.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 4/4] logs.cgi/ids.dat: Use new mechanic to obtain sid info url's
  2026-02-09 14:23 [PATCH 1/4] ruleset-sources: Add details about rule sid and info URL Stefan Schantl
  2026-02-09 14:23 ` [PATCH 2/4] ids-functions.pl: Add function to get the provider by a given rule id Stefan Schantl
  2026-02-09 14:23 ` [PATCH 3/4] ids-functions.pl: Add function to get the info url for " Stefan Schantl
@ 2026-02-09 14:23 ` Stefan Schantl
  2 siblings, 0 replies; 4+ messages in thread
From: Stefan Schantl @ 2026-02-09 14:23 UTC (permalink / raw)
  To: development; +Cc: Stefan Schantl

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 html/cgi-bin/logs.cgi/ids.dat | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/html/cgi-bin/logs.cgi/ids.dat b/html/cgi-bin/logs.cgi/ids.dat
index deebced21..ef224e3e6 100644
--- a/html/cgi-bin/logs.cgi/ids.dat
+++ b/html/cgi-bin/logs.cgi/ids.dat
@@ -22,6 +22,7 @@ use strict;
 my $report_generator_binary = "/usr/bin/suricata-report-generator";
 
 require '/var/ipfire/general-functions.pl';
+require "${General::swroot}/ids-functions.pl";
 require "${General::swroot}/lang.pl";
 require "${General::swroot}/header.pl";
 
@@ -389,21 +390,26 @@ print <<END
 <td valign='top'>
 END
 	;
-	if ($sid eq "n/a") {
-		print $sid;
-	} elsif ($sid < 1000000) {
-		# Link to sourcefire if the the rule sid is less than 1000000.
-		print "<a href='https://www.snort.org/rule_docs/1-$sid' ";
-		print "target='_blank'>$sid</a></td>\n";
-	} elsif ($sid >= 2000000 and $sid < 3000000) {
-		# Link to emergingthreats if the rule sid is between 2000000 and 3000000.
-		print "<a href='https://threatintel.proofpoint.com/sid/$sid' ";
-		print "target='_blank'>$sid</a></td>\n";
+
+	# Check if an valid sid has been found.
+	if ($sid ne "n/a") {
+		# Try to get the info url for the sid.
+		my $info_url = &IDS::get_sid_info_url($sid);
+
+		# Check if an url has been obtained.
+		if ($info_url) {
+			print "<a href='$info_url' ";
+			print "target='_blank'>$sid</a>\n";
+		} else {
+			# No external link available.
+			print $sid;
+		}
 	} else {
 		# No external link for user defined rules
 		print $sid;
 	}
 print <<END
+</td>
 </tr>
 </table><br>
 </td></tr>
-- 
2.47.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-02-09 14:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-09 14:23 [PATCH 1/4] ruleset-sources: Add details about rule sid and info URL Stefan Schantl
2026-02-09 14:23 ` [PATCH 2/4] ids-functions.pl: Add function to get the provider by a given rule id Stefan Schantl
2026-02-09 14:23 ` [PATCH 3/4] ids-functions.pl: Add function to get the info url for " Stefan Schantl
2026-02-09 14:23 ` [PATCH 4/4] logs.cgi/ids.dat: Use new mechanic to obtain sid info url's Stefan Schantl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox