From 6600e62ea386d7801e52a3646c5761df7f10cba0 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 28 Mar 2012 11:39:27 -0400 Subject: [PATCH] Ported scripts using metrics framework and added a new smtp script. - New script measures a couple of aspects of SMTP traffic. - Existing metrics scripts had a small amount of work done to make them work with changes to metrics framework. --- scripts/base/frameworks/metrics/main.bro | 13 ++++---- .../frameworks/metrics/conn-example.bro | 16 ++++------ scripts/policy/protocols/http/detect-sqli.bro | 27 ++++++---------- scripts/policy/protocols/smtp/metrics.bro | 32 +++++++++++++++++++ .../protocols/ssh/detect-bruteforcing.bro | 17 ++++------ 5 files changed, 61 insertions(+), 44 deletions(-) create mode 100644 scripts/policy/protocols/smtp/metrics.bro diff --git a/scripts/base/frameworks/metrics/main.bro b/scripts/base/frameworks/metrics/main.bro index e80054353a..e5ed63dccd 100644 --- a/scripts/base/frameworks/metrics/main.bro +++ b/scripts/base/frameworks/metrics/main.bro @@ -36,6 +36,12 @@ export { network: subnet &optional; } &log; + ## Represents data being added for a single metric data point. Used internally. + type DataPoint: record { + num: count &optional; + unique_vals: set[string] &optional; + }; + ## The record type that is used for logging metrics. type Info: record { ## Timestamp at which the metric was "broken". @@ -142,13 +148,8 @@ export { ## Event to access metrics records as they are passed to the logging framework. global log_metrics: event(rec: Info); - ## Internal use only - type MetricMeasurement: record { - num: count &optional; - unique_vals: set[string] &optional; - }; ## Type to store a table of metrics values. Interal use only! - type MetricTable: table[Index] of MetricMeasurement; + type MetricTable: table[Index] of DataPoint; } redef record Notice::Info += { diff --git a/scripts/policy/frameworks/metrics/conn-example.bro b/scripts/policy/frameworks/metrics/conn-example.bro index 974012963b..00c82f840d 100644 --- a/scripts/policy/frameworks/metrics/conn-example.bro +++ b/scripts/policy/frameworks/metrics/conn-example.bro @@ -4,22 +4,18 @@ @load base/frameworks/metrics @load base/utils/site -redef enum Metrics::ID += { - CONNS_ORIGINATED, - CONNS_RESPONDED -}; - event bro_init() { - Metrics::add_filter(CONNS_ORIGINATED, [$aggregation_mask=24, $break_interval=1mins]); + #Metrics::add_filter("conns.originated", [$aggregation_mask=24, $break_interval=1mins]); + Metrics::add_filter("conns.originated", [$aggregation_table=Site::local_nets_table, $break_interval=1mins]); + # Site::local_nets must be defined in order for this to actually do anything. - Metrics::add_filter(CONNS_RESPONDED, [$aggregation_table=Site::local_nets_table, $break_interval=1mins]); + Metrics::add_filter("conns.responded", [$aggregation_table=Site::local_nets_table, $break_interval=1mins]); } event connection_established(c: connection) { - Metrics::add_data(CONNS_ORIGINATED, [$host=c$id$orig_h], 1); - Metrics::add_data(CONNS_RESPONDED, [$host=c$id$resp_h], 1); + Metrics::add_data("conns.originated", [$host=c$id$orig_h], 1); + Metrics::add_data("conns.responded", [$host=c$id$resp_h], 1); } - diff --git a/scripts/policy/protocols/http/detect-sqli.bro b/scripts/policy/protocols/http/detect-sqli.bro index a92565c63a..193a4b9614 100644 --- a/scripts/policy/protocols/http/detect-sqli.bro +++ b/scripts/policy/protocols/http/detect-sqli.bro @@ -15,13 +15,6 @@ export { SQL_Injection_Victim, }; - redef enum Metrics::ID += { - ## Metric to track SQL injection attackers. - SQLI_ATTACKER, - ## Metrics to track SQL injection victims. - SQLI_VICTIM, - }; - redef enum Tags += { ## Indicator of a URI based SQL injection attack. URI_SQLI, @@ -58,14 +51,14 @@ event bro_init() &priority=3 # determine when it looks like an actual attack and how to respond when # thresholds are crossed. - Metrics::add_filter(SQLI_ATTACKER, [$log=F, - $notice_threshold=sqli_requests_threshold, - $break_interval=sqli_requests_interval, - $note=SQL_Injection_Attacker]); - Metrics::add_filter(SQLI_VICTIM, [$log=F, - $notice_threshold=sqli_requests_threshold, - $break_interval=sqli_requests_interval, - $note=SQL_Injection_Victim]); + Metrics::add_filter("http.sqli.attacker", [$log=F, + $notice_threshold=sqli_requests_threshold, + $break_interval=sqli_requests_interval, + $note=SQL_Injection_Attacker]); + Metrics::add_filter("http.sqli.victim", [$log=F, + $notice_threshold=sqli_requests_threshold, + $break_interval=sqli_requests_interval, + $note=SQL_Injection_Victim]); } event http_request(c: connection, method: string, original_URI: string, @@ -75,7 +68,7 @@ event http_request(c: connection, method: string, original_URI: string, { add c$http$tags[URI_SQLI]; - Metrics::add_data(SQLI_ATTACKER, [$host=c$id$orig_h], 1); - Metrics::add_data(SQLI_VICTIM, [$host=c$id$resp_h], 1); + Metrics::add_data("http.sqli.attacker", [$host=c$id$orig_h], 1); + Metrics::add_data("http.sqli.victim", [$host=c$id$resp_h], 1); } } diff --git a/scripts/policy/protocols/smtp/metrics.bro b/scripts/policy/protocols/smtp/metrics.bro new file mode 100644 index 0000000000..c3d1bb1e20 --- /dev/null +++ b/scripts/policy/protocols/smtp/metrics.bro @@ -0,0 +1,32 @@ +##! This script is meant to answer the following questions... +##! "How many unique 'MAIL FROM' addresses are being used by local mail servers per hour?" +##! "How much mail is being sent from each local mail server per hour?" + +@load base/frameworks/metrics + +module SMTPMetrics; + +export { + ## Define the break intervals for all of the metrics collected and logged by this script. + const breaks = 1hr &redef; +} + +event bro_init() &priority=5 + { + Metrics::add_filter("smtp.mailfrom", [$pred(index: Metrics::Index) = { + return addr_matches_host(index$host, LOCAL_HOSTS); }, + $break_interval=breaks]); + Metrics::add_filter("smtp.messages", [$pred(index: Metrics::Index) = { + return addr_matches_host(index$host, LOCAL_HOSTS); }, + $break_interval=breaks]); + } + +event SMTP::log_smtp(rec: SMTP::Info) + { + Metrics::add_data("smtp.messages", [$host=rec$id$orig_h], 1); + + if ( rec?$mailfrom ) + Metrics::add_unique("smtp.mailfrom", [$host=rec$id$orig_h], rec$mailfrom); + } + + diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index aa6e920c12..7939f00c72 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -20,11 +20,6 @@ export { Login_By_Password_Guesser, }; - redef enum Metrics::ID += { - ## Metric is to measure failed logins. - FAILED_LOGIN, - }; - ## The number of failed SSH connections before a host is designated as ## guessing passwords. const password_guesses_limit = 30 &redef; @@ -46,11 +41,11 @@ export { event bro_init() { - Metrics::add_filter(FAILED_LOGIN, [$name="detect-bruteforcing", $log=F, - $note=Password_Guessing, - $notice_threshold=password_guesses_limit, - $notice_freq=1hr, - $break_interval=guessing_timeout]); + Metrics::add_filter("ssh.login.failure", [$name="detect-bruteforcing", $log=F, + $note=Password_Guessing, + $notice_threshold=password_guesses_limit, + $notice_freq=1hr, + $break_interval=guessing_timeout]); } event SSH::heuristic_successful_login(c: connection) @@ -75,5 +70,5 @@ event SSH::heuristic_failed_login(c: connection) # be ignored. if ( ! (id$orig_h in ignore_guessers && id$resp_h in ignore_guessers[id$orig_h]) ) - Metrics::add_data(FAILED_LOGIN, [$host=id$orig_h], 1); + Metrics::add_data("ssh.login.failure", [$host=id$orig_h], 1); }