mirror of
https://github.com/zeek/zeek.git
synced 2025-10-08 01:28:20 +00:00
Notices actions are now accumulative.
- New log file for auditing the notice policy to see at a specific point in time what the fully ordered (by priority) notice policy was. - New notice action "ACTION_STOP" to stop processing the notice policy. This is essentially how the old IGNORE action can be done with the accumulative notices actions. It just needs to be set as the $result at an at an appropriately high priority. - No longer using the "match" statement as it didn't provide the flexibility to implement accumulative notice actions. The functionality is now implemented completely in script-land. - Beginning removal of action-filters script. Still need to come up with a way to implement some of the functionality of that script. - Small documentation updates.
This commit is contained in:
parent
da635c0c2c
commit
c5f683ee47
3 changed files with 118 additions and 59 deletions
|
@ -1,2 +1,2 @@
|
||||||
@load notice/base
|
@load notice/base
|
||||||
@load notice/action-filters
|
#@load notice/action-filters
|
|
@ -126,6 +126,6 @@ event bro_done()
|
||||||
{
|
{
|
||||||
local n = tallies[s];
|
local n = tallies[s];
|
||||||
local msg = fmt("%s (%d time%s)", s, n, n > 1 ? "s" : "");
|
local msg = fmt("%s (%d time%s)", s, n, n > 1 ? "s" : "");
|
||||||
NOTICE([$note=Notice_Tally, $msg=msg, $n=n]);
|
NOTICE([$note=Notice::Tally, $msg=msg, $n=n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,35 +10,43 @@
|
||||||
module Notice;
|
module Notice;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
# This couldn't be named NOTICE because that id is already used by the
|
redef enum Log::ID += {
|
||||||
# global function NOTICE().
|
## This is the primary logging stream for notices. The logging stream
|
||||||
redef enum Log::ID += { NOTICE_LOG };
|
## couldn't be named NOTICE because that id is already used by the
|
||||||
|
## global function :bro:id:`NOTICE`.
|
||||||
|
NOTICES,
|
||||||
|
## This is the notice policy auditing log. It records what the current
|
||||||
|
## notice policy is at Bro init time..
|
||||||
|
NOTICE_POLICY,
|
||||||
|
};
|
||||||
|
|
||||||
## Scripts creating new notices need to redef this enum to add their own
|
## Scripts creating new notices need to redef this enum to add their own
|
||||||
## specific notice types which would then get used when they call the
|
## specific notice types which would then get used when they call the
|
||||||
## :bro:id:`NOTICE` function. The convention is to give a general category
|
## :bro:id:`NOTICE` function. The convention is to give a general category
|
||||||
## along with the specific notice separating words with underscores and using
|
## along with the specific notice separating words with underscores and using
|
||||||
## leading capitals on each word except for abbreviations which are kept in
|
## leading capitals on each word except for abbreviations which are kept in
|
||||||
## all capitals. For example, SSH_Login is for heuristically guessed
|
## all capitals. For example, SSH::Login is for heuristically guessed
|
||||||
## successful SSH logins.
|
## successful SSH logins.
|
||||||
type Type: enum {
|
type Type: enum {
|
||||||
## Notice reporting a count of how often a notice occurred.
|
## Notice reporting a count of how often a notice occurred.
|
||||||
Notice_Tally,
|
Tally,
|
||||||
};
|
};
|
||||||
|
|
||||||
## These are values representing actions that can be taken with notices.
|
## These are values representing actions that can be taken with notices.
|
||||||
type Action: enum {
|
type Action: enum {
|
||||||
## Indicates that the notice should be sent to the notice file.
|
## Indicates that the notice should be sent to the notice file.
|
||||||
ACTION_FILE,
|
ACTION_FILE,
|
||||||
## Indicates that no action should be taken with the notice.
|
## Indicates that the notice should be alarmed on.
|
||||||
ACTION_IGNORE,
|
|
||||||
## Indicates that the notice should always be turned into an alarm.
|
|
||||||
ACTION_ALARM,
|
ACTION_ALARM,
|
||||||
## Indicates that the notice should be sent to the contact email.
|
## Indicates that the notice should be sent to the configured notice
|
||||||
ACTION_EMAIL,
|
## contact email address(es).
|
||||||
|
ACTION_EMAIL,
|
||||||
## Indicates that the notice should be sent to the configured pager
|
## Indicates that the notice should be sent to the configured pager
|
||||||
## email address.
|
## email address.
|
||||||
ACTION_PAGE,
|
ACTION_PAGE,
|
||||||
|
## Indicates that no more actions should be found after the policy
|
||||||
|
## item returning this matched.
|
||||||
|
ACTION_STOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Info: record {
|
type Info: record {
|
||||||
|
@ -72,19 +80,15 @@ export {
|
||||||
## Associated ICMP "connection".
|
## Associated ICMP "connection".
|
||||||
iconn: icmp_conn &optional;
|
iconn: icmp_conn &optional;
|
||||||
|
|
||||||
## The action assigned to this notice after being processed by the
|
|
||||||
## various action assigning methods.
|
|
||||||
action: Notice::Action &log &default=ACTION_FILE;
|
|
||||||
## Peer that raised this notice.
|
## Peer that raised this notice.
|
||||||
src_peer: event_peer &log &optional;
|
src_peer: event_peer &log &optional;
|
||||||
## Uniquely identifying tag associated with this notice.
|
## Uniquely identifying tag associated with this notice.
|
||||||
tag: string &log &optional;
|
tag: string &log &optional;
|
||||||
|
|
||||||
## This value controls and indicates if notices should be bumped up
|
## The set of actions that are to be applied to this notice.
|
||||||
## to alarms independent of all other notice actions and filters.
|
## TODO: there is a problem setting a &default=set() attribute
|
||||||
## If false, don't alarm independent of the determined notice action.
|
## for sets containing enum values.
|
||||||
## If true, alarm dependening on the notice action.
|
actions: set[Notice::Action] &log &optional;
|
||||||
do_alarm: bool &log &default=F;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
## Ignored notice types.
|
## Ignored notice types.
|
||||||
|
@ -92,10 +96,18 @@ export {
|
||||||
## Emailed notice types.
|
## Emailed notice types.
|
||||||
const emailed_types: set[Notice::Type] = {} &redef;
|
const emailed_types: set[Notice::Type] = {} &redef;
|
||||||
|
|
||||||
|
## This is the record that defines the items that make up the notice policy.
|
||||||
type PolicyItem: record {
|
type PolicyItem: record {
|
||||||
result: Notice::Action &default=ACTION_FILE;
|
## Define the priority for this check. Items are checked in ordered
|
||||||
pred: function(n: Notice::Info): bool;
|
## from highest value (10) to lowest value (0).
|
||||||
priority: count &default=5;
|
priority: count &log &default=5;
|
||||||
|
## An action given to the notice if the predicate return true.
|
||||||
|
result: Notice::Action &log &default=ACTION_FILE;
|
||||||
|
## The pred (predicate) field is a function that returns a boolean T
|
||||||
|
## or F value. If the predicate function return true, the action in
|
||||||
|
## this record is applied to the notice that is given as an argument
|
||||||
|
## to the predicate function.
|
||||||
|
pred: function(n: Notice::Info): bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
# This is the :bro:id:`Notice::policy` where the local notice conversion
|
# This is the :bro:id:`Notice::policy` where the local notice conversion
|
||||||
|
@ -105,11 +117,11 @@ export {
|
||||||
$result = ACTION_FILE,
|
$result = ACTION_FILE,
|
||||||
$priority = 0],
|
$priority = 0],
|
||||||
[$pred(n: Notice::Info) = { return (n$note in ignored_types); },
|
[$pred(n: Notice::Info) = { return (n$note in ignored_types); },
|
||||||
$result = ACTION_IGNORE,
|
$result = ACTION_STOP,
|
||||||
$priority = 1],
|
$priority = 10],
|
||||||
[$pred(n: Notice::Info) = { return (n$note in emailed_types); },
|
[$pred(n: Notice::Info) = { return (n$note in emailed_types); },
|
||||||
$result = ACTION_EMAIL,
|
$result = ACTION_EMAIL,
|
||||||
$priority = 3],
|
$priority = 9],
|
||||||
} &redef;
|
} &redef;
|
||||||
|
|
||||||
## Local system mail program.
|
## Local system mail program.
|
||||||
|
@ -119,6 +131,14 @@ export {
|
||||||
## Email address to send notices with the :bro:enum:`ACTION_PAGE` action.
|
## Email address to send notices with the :bro:enum:`ACTION_PAGE` action.
|
||||||
const mail_page_dest = "" &redef;
|
const mail_page_dest = "" &redef;
|
||||||
|
|
||||||
|
## This is the event that is called as the entry point to the
|
||||||
|
## notice framework by the global :bro:id:`NOTICE` function. By the time
|
||||||
|
## this event is generated, default values have already been filled out in
|
||||||
|
## the :bro:type:`Notice::Info` record and synchronous functions in the
|
||||||
|
## :bro:id:`Notice:notice_functions` have already been called. The notice
|
||||||
|
## policy has also been applied.
|
||||||
|
global notice: event(n: Info);
|
||||||
|
|
||||||
## This is a set of functions that provide a synchronous way for scripts
|
## This is a set of functions that provide a synchronous way for scripts
|
||||||
## extending the notice framework to run before the normal event based
|
## extending the notice framework to run before the normal event based
|
||||||
## notice pathway that most of the notice framework takes. This is helpful
|
## notice pathway that most of the notice framework takes. This is helpful
|
||||||
|
@ -137,13 +157,6 @@ export {
|
||||||
## :bro:enum:`ACTION_PAGE` actions.
|
## :bro:enum:`ACTION_PAGE` actions.
|
||||||
global email_notice_to: function(n: Info, dest: string);
|
global email_notice_to: function(n: Info, dest: string);
|
||||||
|
|
||||||
## This is the event that is called as the entry point to the
|
|
||||||
## notice framework by the global :bro:id:`NOTICE` function. By the time
|
|
||||||
## this event is generated, default values have already been filled out in
|
|
||||||
## the :bro:type:`Notice::Info` record and synchronous functions in the
|
|
||||||
## :bro:id:`Notice:notice_functions` have already been called.
|
|
||||||
global notice: event(n: Info);
|
|
||||||
|
|
||||||
## This is an internally used function, please ignore it. It's only used
|
## This is an internally used function, please ignore it. It's only used
|
||||||
## for filling out missing details of :bro:type:`Notice:Info` records
|
## for filling out missing details of :bro:type:`Notice:Info` records
|
||||||
## before the synchronous and asynchronous event pathways have begun.
|
## before the synchronous and asynchronous event pathways have begun.
|
||||||
|
@ -154,17 +167,25 @@ export {
|
||||||
global log_notice: event(rec: Info);
|
global log_notice: event(rec: Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This is an internal variable used to store the notice policy ordered by
|
||||||
|
# priority.
|
||||||
|
global ordered_policy: vector of PolicyItem = vector();
|
||||||
|
|
||||||
|
|
||||||
redef record Conn::Info += {
|
redef record Conn::Info += {
|
||||||
notice_tags: set[string] &log &optional;
|
notice_tags: set[string] &log &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
event bro_init()
|
event bro_init()
|
||||||
{
|
{
|
||||||
Log::create_stream(NOTICE_LOG, [$columns=Info, $ev=log_notice]);
|
Log::create_stream(NOTICE_POLICY, [$columns=PolicyItem]);
|
||||||
|
|
||||||
|
Log::create_stream(NOTICES, [$columns=Info, $ev=log_notice]);
|
||||||
|
|
||||||
# Add a filter to create the alarm log.
|
# Add a filter to create the alarm log.
|
||||||
Log::add_filter(NOTICE_LOG, [$name = "alarm", $path = "alarm",
|
Log::add_filter(NOTICES, [$name = "alarm", $path = "alarm",
|
||||||
$pred(rec: Notice::Info) = { return rec$do_alarm; }]);
|
$pred(rec: Notice::Info) = { return (ACTION_ALARM in rec$actions); }]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: fix this.
|
# TODO: fix this.
|
||||||
|
@ -199,13 +220,6 @@ function email_notice_to(n: Notice::Info, dest: string)
|
||||||
system(mail_cmd);
|
system(mail_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
function email_notice(n: Notice::Info)
|
|
||||||
{
|
|
||||||
# Choose destination address based on action type.
|
|
||||||
local dest = (n$action == ACTION_EMAIL) ? mail_dest : mail_page_dest;
|
|
||||||
email_notice_to(n, dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Executes a script with all of the notice fields put into the
|
# Executes a script with all of the notice fields put into the
|
||||||
# new process' environment as "BRO_ARG_<field>" variables.
|
# new process' environment as "BRO_ARG_<field>" variables.
|
||||||
function execute_with_notice(cmd: string, n: Notice::Info)
|
function execute_with_notice(cmd: string, n: Notice::Info)
|
||||||
|
@ -229,7 +243,7 @@ function apply_policy(n: Notice::Info)
|
||||||
if ( ! n?$id )
|
if ( ! n?$id )
|
||||||
n$id = n$conn$id;
|
n$id = n$conn$id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! n?$src && n?$id )
|
if ( ! n?$src && n?$id )
|
||||||
n$src = n$id$orig_h;
|
n$src = n$id$orig_h;
|
||||||
if ( ! n?$dst && n?$id )
|
if ( ! n?$dst && n?$id )
|
||||||
|
@ -246,25 +260,38 @@ function apply_policy(n: Notice::Info)
|
||||||
if ( ! n?$src_peer )
|
if ( ! n?$src_peer )
|
||||||
n$src_peer = get_event_peer();
|
n$src_peer = get_event_peer();
|
||||||
|
|
||||||
if ( ! n?$do_alarm )
|
if ( ! n?$actions )
|
||||||
n$do_alarm = F;
|
n$actions = set();
|
||||||
|
|
||||||
# Generate a unique ID for this notice.
|
# Generate a unique ID for this notice.
|
||||||
n$tag = unique_id("@");
|
n$tag = unique_id("@");
|
||||||
|
|
||||||
n$action = match n using policy;
|
for ( i in ordered_policy )
|
||||||
|
{
|
||||||
|
if ( ordered_policy[i]$pred(n) )
|
||||||
|
{
|
||||||
|
# If the predicate
|
||||||
|
add n$actions[ordered_policy[i]$result];
|
||||||
|
|
||||||
|
# This is the one special case for notice actions because it's
|
||||||
|
# acting as a stopper to the notice policy evaluation.
|
||||||
|
if ( ordered_policy[i]$result == ACTION_STOP )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event notice(n: Notice::Info) &priority=-5
|
event notice(n: Notice::Info) &priority=-5
|
||||||
{
|
{
|
||||||
# Don't do anything if this notice is to be ignored.
|
if ( ACTION_EMAIL in n$actions )
|
||||||
if ( n$action == ACTION_IGNORE )
|
email_notice_to(n, mail_dest);
|
||||||
return;
|
|
||||||
|
|
||||||
if ( n$action == ACTION_EMAIL || n$action == ACTION_PAGE )
|
if ( ACTION_PAGE in n$actions )
|
||||||
email_notice(n);
|
email_notice_to(n, mail_page_dest);
|
||||||
|
|
||||||
# Add the tag to the connection's notice_tags if there is a connection.
|
# Add the tag to the connection's notice_tags if there is a connection.
|
||||||
|
# TODO: figure out how to move this to the conn scripts. This should
|
||||||
|
# cause protocols/conn to be a dependency.
|
||||||
if ( n?$conn && n$conn?$conn )
|
if ( n?$conn && n$conn?$conn )
|
||||||
{
|
{
|
||||||
if ( ! n$conn$conn?$notice_tags )
|
if ( ! n$conn$conn?$notice_tags )
|
||||||
|
@ -272,27 +299,59 @@ event notice(n: Notice::Info) &priority=-5
|
||||||
add n$conn$conn$notice_tags[n$tag];
|
add n$conn$conn$notice_tags[n$tag];
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::write(NOTICE_LOG, n);
|
Log::write(NOTICES, n);
|
||||||
|
|
||||||
@ifdef ( IDMEF_support )
|
@ifdef ( IDMEF_support )
|
||||||
if ( n?$id )
|
if ( n?$id )
|
||||||
generate_idmef(n$id$orig_h, n$id$orig_p, n$id$resp_h, n$id$resp_p);
|
generate_idmef(n$id$orig_h, n$id$orig_p, n$id$resp_h, n$id$resp_p);
|
||||||
@endif
|
@endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Create the ordered notice policy automatically which will be used at runtime
|
||||||
|
# for prioritized matching of the notice policy.
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
local tmp: table[count] of set[PolicyItem] = table();
|
||||||
|
for ( pi in policy )
|
||||||
|
{
|
||||||
|
if ( pi$priority < 0 || pi$priority > 10 )
|
||||||
|
{
|
||||||
|
print "All Notice::PolicyItem priorities must be within 0 and 10";
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pi$priority !in tmp )
|
||||||
|
tmp[pi$priority] = set();
|
||||||
|
add tmp[pi$priority][pi];
|
||||||
|
}
|
||||||
|
|
||||||
|
local rev_count = vector(10,9,8,7,6,5,4,3,2,1,0);
|
||||||
|
for ( i in rev_count )
|
||||||
|
{
|
||||||
|
local j = rev_count[i];
|
||||||
|
if ( j in tmp )
|
||||||
|
{
|
||||||
|
for ( pi in tmp[j] )
|
||||||
|
{
|
||||||
|
ordered_policy[|ordered_policy|] = pi;
|
||||||
|
Log::write(NOTICE_POLICY, pi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module GLOBAL;
|
module GLOBAL;
|
||||||
|
|
||||||
## This is the wrapper in the global namespace for the :bro:id:`Notice::notice`
|
## This is the entry point in the global namespace for notice framework.
|
||||||
## event.
|
|
||||||
function NOTICE(n: Notice::Info)
|
function NOTICE(n: Notice::Info)
|
||||||
{
|
{
|
||||||
# Fill out fields that might be empty and do the policy processing.
|
# Fill out fields that might be empty and do the policy processing.
|
||||||
Notice::apply_policy(n);
|
Notice::apply_policy(n);
|
||||||
|
|
||||||
# Run the synchronous functions with the notice.
|
# Run the synchronous functions with the notice.
|
||||||
for ( func in Notice::notice_functions )
|
for ( func in Notice::notice_functions )
|
||||||
{
|
|
||||||
func(n);
|
func(n);
|
||||||
}
|
|
||||||
# Generate the notice event with the notice.
|
# Generate the notice event with the notice.
|
||||||
event Notice::notice(n);
|
event Notice::notice(n);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue