diff --git a/policy/CMakeLists.txt b/policy/CMakeLists.txt index a79e841661..10a92a550d 100644 --- a/policy/CMakeLists.txt +++ b/policy/CMakeLists.txt @@ -1,10 +1,19 @@ +include(InstallPackageConfigFile) + install(DIRECTORY ./ DESTINATION ${POLICYDIR} FILES_MATCHING PATTERN "summaries" EXCLUDE PATTERN "all.bro" EXCLUDE + PATTERN "site/local.bro" EXCLUDE PATTERN "bro.init" PATTERN "*.bro" PATTERN "*.sig" PATTERN "*.osf" ) -install(DIRECTORY DESTINATION ${POLICYDIR}/site) +# Install as a config file since the local.bro script is meant to be +# user modify-able. +InstallPackageConfigFile( + ${CMAKE_CURRENT_SOURCE_DIR}/site/local.bro + ${POLICYDIR}/site + local.bro) + diff --git a/policy/bro.init b/policy/bro.init index dd0e066627..fda8cfd6f4 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -1275,7 +1275,7 @@ const log_rotate_interval = 0 sec &redef; # If set, rotate logs at given time + i * log_rotate_interval. # (string is time in 24h format, e.g., "18:00"). -const log_rotate_base_time = "" &redef; +const log_rotate_base_time = "0:00" &redef; # Rotate logs when they reach this size (in bytes). Note, the # parameter is a double rather than a count to enable easy expression diff --git a/policy/frameworks/cluster/base/main.bro b/policy/frameworks/cluster/base/main.bro index ab35bc8f86..700721aac8 100644 --- a/policy/frameworks/cluster/base/main.bro +++ b/policy/frameworks/cluster/base/main.bro @@ -33,10 +33,6 @@ export { ## connecting to a running instance to update settings or request data. const control_events = Control::controller_events &redef; - ## Directory where the cluster is archiving logs. - ## TODO: we need a sane default here. - const log_dir = "/not/set" &redef; - ## Record type to indicate a node in a cluster. type Node: record { node_type: NodeType; diff --git a/policy/frameworks/cluster/base/node/manager.bro b/policy/frameworks/cluster/base/node/manager.bro index eec61ea5cd..3a4dbac83f 100644 --- a/policy/frameworks/cluster/base/node/manager.bro +++ b/policy/frameworks/cluster/base/node/manager.bro @@ -22,6 +22,5 @@ redef max_remote_events_processed = 10000; event Notice::notice(n: Notice::Info) { if ( is_remote_event() ) - #if ( FilterDuplicates::is_new(n) ) NOTICE(n); - } \ No newline at end of file + } diff --git a/policy/frameworks/cluster/base/node/worker.bro b/policy/frameworks/cluster/base/node/worker.bro index 6e6144da5c..038d8250da 100644 --- a/policy/frameworks/cluster/base/node/worker.bro +++ b/policy/frameworks/cluster/base/node/worker.bro @@ -14,5 +14,9 @@ redef Log::default_rotation_postprocessor = "delete-log"; # TODO: should we really be setting this to T? redef record_all_packets = T; -# TODO: Workers need to have a filter for the notice log which doesn't -# do remote logging since we forward the notice event directly. \ No newline at end of file +# Workers need to have a filter for the notice log which doesn't +# do remote logging since we forward the notice event directly. +event bro_init() + { + Log::add_filter(Notice::NOTICE, [$pred(n: Notice::Info) = { return F; }]); + } \ No newline at end of file diff --git a/policy/frameworks/control/base/main.bro b/policy/frameworks/control/base/main.bro index 001126d19f..9bcd4bcbe5 100644 --- a/policy/frameworks/control/base/main.bro +++ b/policy/frameworks/control/base/main.bro @@ -4,6 +4,11 @@ ##! ##! Intended to be used from the command line like this when starting a controller: ##! bro frameworks/control/controller Control::host= Control::port= Control::cmd= [Control::arg=] +##! +##! A controllee only needs to load the controllee script in addition +##! to the specific analysis scripts desired. It may also need a noded +##! configured as a controller node in the communications nodes configuration. +##! bro frameworks/control/controllee ##! ##! To use the framework as a controllee, it only needs to be loaded and ##! the controlled node need to accept all events in the "Control::" namespace @@ -21,8 +26,7 @@ export { ## This is the command that is being done. It's typically set on the ## command line and influences whether this instance starts up as a - ## controller or controllee. If left blank this node will start as a - ## controllee and a controller if there is a given command. + ## controller or controllee. const cmd = "" &redef; ## This can be used by commands that take an argument. diff --git a/policy/frameworks/control/controllee.bro b/policy/frameworks/control/controllee.bro index c62fe409f8..9080979e5f 100644 --- a/policy/frameworks/control/controllee.bro +++ b/policy/frameworks/control/controllee.bro @@ -21,9 +21,13 @@ event Control::peer_status_request() local peer = Communication::nodes[p]; if ( ! peer$connected ) next; - - status += fmt("peer=%s host=%s events_in=? events_out=? ops_in=? ops_out=? bytes_in=? bytes_out=?\n", - peer$peer$descr, peer$host); + + local res = resource_usage(); + status += fmt("%.6f peer=%s host=%s events_in=%s events_out=%s ops_in=%s ops_out=%s bytes_in=? bytes_out=?\n", + network_time(), + peer$peer$descr, peer$host, + res$num_events_queued, res$num_events_dispatched, + res$blocking_input, res$blocking_output); } event Control::peer_status_response(status); diff --git a/policy/frameworks/dpd/base/main.bro b/policy/frameworks/dpd/base/main.bro index a2ae4d5b94..fc361f4950 100644 --- a/policy/frameworks/dpd/base/main.bro +++ b/policy/frameworks/dpd/base/main.bro @@ -96,7 +96,7 @@ event protocol_violation(c: connection, atype: count, aid: count, reason: string local size = c$orig$size + c$resp$size; if ( ignore_violations_after > 0 && size > ignore_violations_after ) return; - + # Disable the analyzer that raised the last core-generated event. disable_analyzer(c$id, aid); add c$dpd$disabled_aids[aid]; diff --git a/policy/frameworks/notice/__load__.bro b/policy/frameworks/notice/__load__.bro index 0c64e2d8a3..3c3c718cbe 100644 --- a/policy/frameworks/notice/__load__.bro +++ b/policy/frameworks/notice/__load__.bro @@ -1,2 +1,4 @@ -@load frameworks/notice/base -@load frameworks/notice/weird +@load ./base + +# Load the script to add hostnames to emails by default. +@load ./extend-email/hostnames \ No newline at end of file diff --git a/policy/frameworks/notice/base/__load__.bro b/policy/frameworks/notice/base/__load__.bro new file mode 100644 index 0000000000..51a76b3411 --- /dev/null +++ b/policy/frameworks/notice/base/__load__.bro @@ -0,0 +1,9 @@ +@load ./main +@load ./weird + +# There should be no overhead imposed by loading notice actions so we +# load them all. +@load ./actions/drop +@load ./actions/email_admin +@load ./actions/page + diff --git a/policy/frameworks/notice/base/actions/drop.bro b/policy/frameworks/notice/base/actions/drop.bro new file mode 100644 index 0000000000..fc1f608f9f --- /dev/null +++ b/policy/frameworks/notice/base/actions/drop.bro @@ -0,0 +1,34 @@ +##! This script extends the built in notice code to implement the IP address +##! dropping functionality. + +module Notice; + +export { + redef enum Action += { + ## Drops the address via Drop::drop_address, and generates an alarm. + ACTION_DROP + }; + + redef record Info += { + ## Indicate if the $src IP address was dropped and denied network access. + dropped: bool &log &default=F; + }; +} + +# This is a little awkward because we want to inject drop along with the +# synchronous functions. +event bro_init() + { + local drop_func = function(n: Notice::Info) + { + if ( ACTION_DROP in n$actions ) + { + #local drop = React::drop_address(n$src, ""); + #local addl = drop?$sub ? fmt(" %s", drop$sub) : ""; + #n$dropped = drop$note != Drop::AddressDropIgnored; + #n$msg += fmt(" [%s%s]", drop$note, addl); + } + }; + + add Notice::sync_functions[drop_func]; + } \ No newline at end of file diff --git a/policy/frameworks/notice/base/actions/email_admin.bro b/policy/frameworks/notice/base/actions/email_admin.bro new file mode 100644 index 0000000000..07a6568327 --- /dev/null +++ b/policy/frameworks/notice/base/actions/email_admin.bro @@ -0,0 +1,28 @@ + +module Notice; + +export { + redef enum Action += { + ## Indicate that the generated email should be addressed to the + ## appropriate email addresses as found in the + ## :bro:id:`Site::addr_to_emails` variable based on the relevant + ## address or addresses indicated in the notice. + ACTION_EMAIL_ADMIN + }; +} + +event notice(n: Notice::Info) &priority=-5 + { + if ( |Site::local_admins| > 0 && + ACTION_EMAIL_ADMIN in n$actions ) + { + local email = ""; + if ( n?$src && |Site::get_emails(n$src)| > 0 ) + email = fmt("%s, %s", email, Site::get_emails(n$src)); + if ( n?$dst && |Site::get_emails(n$dst)| > 0 ) + email = fmt("%s, %s", email, Site::get_emails(n$dst)); + + if ( email != "" ) + email_notice_to(n, email, T); + } + } \ No newline at end of file diff --git a/policy/frameworks/notice/base/actions/page.bro b/policy/frameworks/notice/base/actions/page.bro new file mode 100644 index 0000000000..059a92c0c9 --- /dev/null +++ b/policy/frameworks/notice/base/actions/page.bro @@ -0,0 +1,19 @@ + +module Notice; + +export { + redef enum Action += { + ## Indicates that the notice should be sent to the pager email address + ## configured in the :bro:id:`mail_page_dest` variable. + ACTION_PAGE + }; + + ## Email address to send notices with the :bro:enum:`Notice::ACTION_PAGE` action. + const mail_page_dest = "" &redef; +} + +event notice(n: Notice::Info) &priority=-5 + { + if ( ACTION_PAGE in n$actions ) + email_notice_to(n, mail_page_dest, F); + } \ No newline at end of file diff --git a/policy/frameworks/notice/base.bro b/policy/frameworks/notice/base/main.bro similarity index 67% rename from policy/frameworks/notice/base.bro rename to policy/frameworks/notice/base/main.bro index c5de300068..2ed7fc1690 100644 --- a/policy/frameworks/notice/base.bro +++ b/policy/frameworks/notice/base/main.bro @@ -16,6 +16,8 @@ export { ## This is the notice policy auditing log. It records what the current ## notice policy is at Bro init time. NOTICE_POLICY, + ## This is the alarm stream. + ALARM, }; ## Scripts creating new notices need to redef this enum to add their own @@ -34,26 +36,13 @@ export { type Action: enum { ## Indicates that there is no action to be taken. ACTION_NONE, - ## Indicates that the notice should be sent to the notice file. - ACTION_FILE, - ## Indicates that the notice should be alarmed on. - ACTION_ALARM, + ## Indicates that the notice should be sent to the notice logging stream. + ACTION_LOG, ## Indicates that the notice should be sent to the email address(es) - ## configured in the :bro:id:`mail_dest` variable. + ## configured in the :bro:id:`Notice::mail_dest` variable. ACTION_EMAIL, - ## Indicate that the generated email should be addressed to the - ## appropriate email addresses as found in the - ## :bro:id:`Site::addr_to_emails` variable based on the originator - ## of the connection or the $src field. - ACTION_EMAIL_ADMIN_ORIG, - ## Indicate that the generated email should be addressed to the - ## appropriate email addresses as found in the - ## :bro:id:`Site::addr_to_emails` variable based on the responder - ## of the connection or the $dst field. - ACTION_EMAIL_ADMIN_RESP, - ## Indicates that the notice should be sent to the pager email address - ## configured in the :bro:id:`mail_page_dest` variable. - ACTION_PAGE, + ## Indicates that the notice should be alarmed. + ACTION_ALARM, }; type Info: record { @@ -61,44 +50,45 @@ export { uid: string &log &optional; id: conn_id &log &optional; - ## The victim of the notice. This can be used in cases where there - ## is a definite loser for a notice. In cases where there isn't a - ## victim, this field should be left empty. - victim: addr &log &optional; + ## These are shorthand ways of giving the uid and id to a notice. The + ## reference to the actual connection will be deleted after applying + ## the notice policy. + conn: connection &optional; + iconn: icmp_conn &optional; ## The :bro:enum:`Notice::Type` of the notice. note: Type &log; ## The human readable message for the notice. msg: string &log &optional; - ## Sub-message. + ## The human readable sub-message. sub: string &log &optional; - - ## Source address, if we don't have a connection. + + ## Source address, if we don't have a :bro:type:`conn_id`. src: addr &log &optional; ## Destination address. dst: addr &log &optional; - ## Associated port, if we don't have a connection. + ## Associated port, if we don't have a :bro:type:`conn_id`. p: port &log &optional; ## Associated count, or perhaps a status code. n: count &log &optional; - - ## Connection associated with the notice. - conn: connection &optional; - ## Associated ICMP "connection". - iconn: icmp_conn &optional; - - ## Peer that raised this notice. - src_peer: event_peer &log &optional; - ## Uniquely identifying tag associated with this notice. - tag: string &log &optional; - ## The set of actions that are to be applied to this notice. - ## TODO: there is a problem setting a &default=set() attribute - ## for sets containing enum values. + ## Peer that raised this notice. + src_peer: event_peer &optional; + ## Textual description for the peer that raised this notice. + peer_descr: string &log &optional; + + ## The actions that are to be applied to this notice. The set[count] + ## is to indicate which :bro:id:`Notice::policy` items + ## triggered the action being added to the notice. actions: set[Notice::Action] &log &optional; + ## These are policy items that returned T and applied their action + ## to the notice. + ## TODO: this can't take set() as a default. (bug) + policy_items: set[count] &log &optional; + ## By adding chunks of text into this element, other scripts can - ## expand on notices that being emailed. The normal way to add text + ## expand on notices that are being emailed. The normal way to add text ## is to extend the vector by handling the :bro:id:`Notice::notice` ## event and modifying the notice in place. email_body_sections: vector of string &default=vector(); @@ -108,9 +98,14 @@ export { const ignored_types: set[Notice::Type] = {} &redef; ## Emailed notice types. const emailed_types: set[Notice::Type] = {} &redef; + ## Alarmed notice types. + const alarmed_types: set[Notice::Type] = {} &redef; ## This is the record that defines the items that make up the notice policy. type PolicyItem: record { + ## This is the exact positional order in which the :id:type:`PolicyItem` + ## records are checked. This is set internally by the notice framework. + position: count &log &optional; ## Define the priority for this check. Items are checked in ordered ## from highest value (10) to lowest value (0). priority: count &log &default=5; @@ -126,31 +121,38 @@ export { halt: bool &log &default=F; }; - # This is the :bro:id:`Notice::policy` where the local notice conversion - # policy is set. - const policy: set[Notice::PolicyItem] = { + ## This is the where the :bro:id:`Notice::policy` is defined. All notice + ## processing is done through this variable. + const policy: set[PolicyItem] = { [$pred(n: Notice::Info) = { return (n$note in Notice::ignored_types); }, - $halt=T, $priority = 10], + $halt=T, $priority = 9], + [$pred(n: Notice::Info) = { return (n$note in Notice::alarmed_types); }, + $priority = 8], [$pred(n: Notice::Info) = { return (n$note in Notice::emailed_types); }, $result = ACTION_EMAIL, - $priority = 9], + $priority = 8], [$pred(n: Notice::Info) = { return T; }, - $result = ACTION_FILE, + $result = ACTION_LOG, $priority = 0], } &redef; - ## Local system mail program. - const mail_script = "/bin/mail" &redef; + ## Local system sendmail program. + const sendmail = "/usr/sbin/sendmail" &redef; ## Email address to send notices with the :bro:enum:`ACTION_EMAIL` action. - const mail_dest = "" &redef; - ## Email address to send notices with the :bro:enum:`ACTION_PAGE` action. - const mail_page_dest = "" &redef; + const mail_dest = "" &redef; + + ## Address that emails will be from. + const mail_from = "Big Brother " &redef; + ## Reply-to address used in outbound email. + const reply_to = "" &redef; + ## Text string prefixed to the subject of all emails sent out. + const mail_subject_prefix = "[Bro]" &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 + ## :bro:id:`Notice:sync_functions` have already been called. The notice ## policy has also been applied. global notice: event(n: Info); @@ -165,7 +167,7 @@ export { ## Normally the event based extension model using the ## :bro:id:`Notice::notice` event will work fine if there aren't harder ## real time constraints. - const notice_functions: set[function(n: Notice::Info)] = set() &redef; + const sync_functions: set[function(n: Notice::Info)] = set() &redef; ## Call this function to send a notice in an email. It is already used ## by default with the built in :bro:enum:`ACTION_EMAIL` and @@ -182,21 +184,25 @@ export { global log_notice: event(rec: Info); } -# This is an internal variable used to store the notice policy ordered by +# This is an internal variable used to store the notice policy ordered by # priority. global ordered_policy: vector of PolicyItem = vector(); event bro_init() { Log::create_stream(NOTICE_POLICY, [$columns=PolicyItem]); - Log::create_stream(Notice::NOTICE, [$columns=Info, $ev=log_notice]); - # Add a filter to create the alarm log. - Log::add_filter(Notice::NOTICE, [$name = "alarm", $path = "alarm", - $pred(rec: Notice::Info) = { return (ACTION_ALARM in rec$actions); }]); - + Log::create_stream(ALARM, [$columns=Notice::Info]); + # Make sure that this log is output as text so that it can be packaged + # up and emailed later. + Log::add_filter(ALARM, [$name="default", $writer=Log::WRITER_ASCII]); } + # TODO: need a way to call a Bro script level callback during file rotation. + # we need more than a just $postprocessor. + #redef Log::rotation_control += { + # [Log::WRITER_ASCII, "alarm"] = [$postprocessor="mail-alarms"]; + #}; # TODO: fix this. #function notice_tags(n: Notice::Info) : table[string] of string @@ -220,25 +226,48 @@ function email_notice_to(n: Notice::Info, dest: string, extend: bool) { if ( reading_traces() || dest == "" ) return; + + local email_text = cat( + "From: ", mail_from, "\n", + "Subject: ", mail_subject_prefix, " ", n$note, "\n", + "To: ", dest, "\n", + # TODO: BiF to get version (the resource_usage Bif seems like overkill). + "User-Agent: Bro-IDS/?.?.?\n"); + + if ( reply_to != "" ) + email_text = cat(email_text, "Reply-To: ", reply_to, "\n"); # The notice emails always start off with the human readable message. - local email_text = n$msg; + email_text = cat(email_text, "\n", n$msg, "\n"); + + # Add the extended information if it's requested. if ( extend ) { - email_text = cat(email_text, "\n\n------------------\n"); for ( i in n$email_body_sections ) - email_text = cat(email_text, n$email_body_sections[i]); + { + email_text = cat(email_text, "******************\n"); + email_text = cat(email_text, n$email_body_sections[i], "\n"); + } } - # The contortions here ensure that the arguments to the mail - # script will not be confused. Re-evaluate if 'system' is reworked. + email_text = cat(email_text, "\n\n--\n[Automatically generated]\n\n"); + local mail_cmd = - fmt("echo \"%s\" | %s -s \"[Bro Alarm] %s\" %s", - str_shell_escape(email_text), mail_script, n$note, dest); - + fmt("echo \"%s\" | %s -t -oi %s", + str_shell_escape(email_text), sendmail); system(mail_cmd); } +event notice(n: Notice::Info) &priority=-5 + { + if ( ACTION_EMAIL in n$actions ) + email_notice_to(n, mail_dest, T); + if ( ACTION_LOG in n$actions ) + Log::write(Notice::NOTICE, n); + if ( ACTION_ALARM in n$actions ) + Log::write(ALARM, n); + } + # Executes a script with all of the notice fields put into the # new process' environment as "BRO_ARG_" variables. function execute_with_notice(cmd: string, n: Notice::Info) @@ -254,81 +283,65 @@ function execute_with_notice(cmd: string, n: Notice::Info) function apply_policy(n: Notice::Info) { # Fill in some defaults. - n$ts = network_time(); + if ( ! n?$ts ) + n$ts = network_time(); if ( n?$conn ) { - if ( ! n?$uid ) - n$uid = n$conn$uid; if ( ! n?$id ) n$id = n$conn$id; + if ( ! n?$uid ) + n$uid = n$conn$uid; } - if ( ! n?$src && n?$id ) - n$src = n$id$orig_h; - if ( ! n?$dst && n?$id ) - n$dst = n$id$resp_h; + if ( n?$id ) + { + if ( ! n?$src ) + n$src = n$id$orig_h; + if ( ! n?$dst ) + n$dst = n$id$resp_h; + if ( ! n?$p ) + n$p = n$id$resp_p; + } - if ( ! n?$p && n?$id ) - n$p = n$id$resp_p; - - if ( ! n?$src && n?$iconn ) - n$src = n$iconn$orig_h; - if ( ! n?$dst && n?$iconn ) - n$dst = n$iconn$resp_h; + if ( n?$iconn ) + { + if ( ! n?$src ) + n$src = n$iconn$orig_h; + if ( ! n?$dst ) + n$dst = n$iconn$resp_h; + } if ( ! n?$src_peer ) n$src_peer = get_event_peer(); - + n$peer_descr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host); + if ( ! n?$actions ) n$actions = set(); - # Generate a unique ID for this notice. - n$tag = unique_id("@"); + if ( ! n?$policy_items ) + n$policy_items = set(); for ( i in ordered_policy ) { if ( ordered_policy[i]$pred(n) ) { - # If the predicate matched, the result of the PolicyItem is added - # to the notices actions. add n$actions[ordered_policy[i]$result]; + add n$policy_items[int_to_count(i)]; # If the policy item wants to halt policy processing, do it now! if ( ordered_policy[i]$halt ) break; } } - } -event notice(n: Notice::Info) &priority=-5 - { - if ( ACTION_EMAIL in n$actions ) - email_notice_to(n, mail_dest, T); - - if ( ACTION_PAGE in n$actions ) - email_notice_to(n, mail_page_dest, F); - - if ( |Site::local_admins| > 0 ) - { - local email = ""; - if ( n?$src && ACTION_EMAIL_ADMIN_ORIG in n$actions ) - { - email = Site::get_emails(n$src); - if ( email != "" ) - email_notice_to(n, email, T); - } - - if ( n?$dst && ACTION_EMAIL_ADMIN_RESP in n$actions ) - { - email = Site::get_emails(n$dst); - if ( email != "" ) - email_notice_to(n, email, T); - } - } - - if ( ACTION_FILE in n$actions ) - Log::write(Notice::NOTICE, n); + # Delete the connection record if it's there so we aren't sending that + # to remote machines. It can cause problems due to the size of the + # connection record. + if ( n?$conn ) + delete n$conn; + if ( n?$iconn ) + delete n$iconn; } # Create the ordered notice policy automatically which will be used at runtime @@ -357,6 +370,7 @@ event bro_init() { for ( pi in tmp[j] ) { + pi$position = |ordered_policy|; ordered_policy[|ordered_policy|] = pi; Log::write(NOTICE_POLICY, pi); } @@ -373,7 +387,7 @@ function NOTICE(n: Notice::Info) Notice::apply_policy(n); # Run the synchronous functions with the notice. - for ( func in Notice::notice_functions ) + for ( func in Notice::sync_functions ) func(n); # Generate the notice event with the notice. diff --git a/policy/frameworks/notice/weird.bro b/policy/frameworks/notice/base/weird.bro similarity index 97% rename from policy/frameworks/notice/weird.bro rename to policy/frameworks/notice/base/weird.bro index b534e0e7af..149df5ea2b 100644 --- a/policy/frameworks/notice/weird.bro +++ b/policy/frameworks/notice/base/weird.bro @@ -1,9 +1,11 @@ -@load frameworks/notice/base +@load frameworks/notice @load utils/conn-ids module Weird; export { + redef enum Log::ID += { WEIRD }; + redef enum Notice::Type += { ## Generic unusual but alarm-worthy activity. WeirdActivity, @@ -15,8 +17,6 @@ export { ContentGap, }; - redef enum Log::ID += { WEIRD }; - type Info: record { ts: time &log; uid: string &log &optional; @@ -59,7 +59,7 @@ export { ["baroque_SYN"] = WEIRD_FILE, ["base64_illegal_encoding"] = WEIRD_FILE, ["connection_originator_SYN_ack"] = WEIRD_FILE, - ["corrupt_tcp_options"] = WEIRD_FILE, + ["corrupt_tcp_options"] = WEIRD_NOTICE_PER_ORIG, ["crud_trailing_HTTP_request"] = WEIRD_FILE, ["data_after_reset"] = WEIRD_FILE, ["data_before_established"] = WEIRD_FILE, @@ -200,10 +200,10 @@ export { # Code Red generates slews ... ["excessively_small_fragment"] = WEIRD_NOTICE_PER_ORIG, - ["fragment_inconsistency"] = WEIRD_NOTICE_ALWAYS, - ["fragment_overlap"] = WEIRD_NOTICE_ALWAYS, + ["fragment_inconsistency"] = WEIRD_NOTICE_PER_ORIG, + ["fragment_overlap"] = WEIRD_NOTICE_PER_ORIG, ["fragment_protocol_inconsistency"] = WEIRD_NOTICE_ALWAYS, - ["fragment_size_inconsistency"] = WEIRD_NOTICE_ALWAYS, + ["fragment_size_inconsistency"] = WEIRD_NOTICE_PER_ORIG, ["fragment_with_DF"] = WEIRD_FILE, # these do indeed happen! ["incompletely_captured_fragment"] = WEIRD_NOTICE_ALWAYS, @@ -217,6 +217,9 @@ export { # generated by policy script ["Land_attack"] = WEIRD_NOTICE_PER_ORIG, ["bad_pm_port"] = WEIRD_NOTICE_PER_ORIG, + + ["ICMP-unreachable for wrong state"] = WEIRD_NOTICE_PER_ORIG, + } &redef; # table that maps weird types into a function that should be called diff --git a/policy/frameworks/notice/extend-email/hostnames.bro b/policy/frameworks/notice/extend-email/hostnames.bro new file mode 100644 index 0000000000..e7c7470b3c --- /dev/null +++ b/policy/frameworks/notice/extend-email/hostnames.bro @@ -0,0 +1,36 @@ + +module Notice; + +# This probably doesn't actually work due to the async lookup_addr. +event Notice::notice(n: Notice::Info) &priority=10 + { + if ( ! n?$src && ! n?$dst ) + return; + + local output = ""; + if ( n?$src ) + { + when ( local src_name = lookup_addr(n$src) ) + { + output = cat(output, "orig_h/src: ", src_name, "\n"); + } + timeout 5secs + { + output = cat(output, "orig_h/src: \n"); + } + } + if ( n?$dst ) + { + when ( local dst_name = lookup_addr(n$dst) ) + { + output = cat(output, "resp_h/dst: ", dst_name, "\n"); + } + timeout 5secs + { + output = cat(output, "resp_h/dst: \n"); + } + } + + if ( output != "" ) + n$email_body_sections[|n$email_body_sections|] = output; + } \ No newline at end of file diff --git a/policy/frameworks/packet-filter/base/main.bro b/policy/frameworks/packet-filter/base/main.bro index 9b9925fcdf..a2336b7d61 100644 --- a/policy/frameworks/packet-filter/base/main.bro +++ b/policy/frameworks/packet-filter/base/main.bro @@ -44,11 +44,11 @@ export { ## changed however to enable port-independent protocol analysis. const all_packets = T &redef; - ## Filter string which is unconditionally or'ed to every dynamically - ## built filter. + ## Filter string which is unconditionally or'ed to the beginning of every + ## dynamically built filter. const unrestricted_filter = "" &redef; - ## Call this function to build and install a new dynamically build + ## Call this function to build and install a new dynamically built ## packet filter. global install: function(); diff --git a/policy/misc/analysis-groups.bro b/policy/misc/analysis-groups.bro index 438ef92556..1e5a784226 100644 --- a/policy/misc/analysis-groups.bro +++ b/policy/misc/analysis-groups.bro @@ -24,8 +24,8 @@ event Control::configuration_update() if ( g !in disabled ) enable_event_group(g); - # Disable those which are not already. - for ( g in disable_event_group ) + # Disable those which are not already disabled. + for ( g in disabled ) if ( g !in currently_disabled ) disable_event_group(g); diff --git a/policy/misc/trim-trace-file.bro b/policy/misc/trim-trace-file.bro index 918175295a..3caa41c06b 100644 --- a/policy/misc/trim-trace-file.bro +++ b/policy/misc/trim-trace-file.bro @@ -5,7 +5,7 @@ module TrimTraceFile; export { ## The interval between times that the output tracefile is rotated. - const trim_interval = 5 secs &redef; + const trim_interval = 10 mins &redef; ## This event can be generated externally to this script if on-demand ## tracefile rotation is required with the caveat that the script doesn't diff --git a/policy/protocols/dns/base/main.bro b/policy/protocols/dns/base/main.bro index c82906b1e5..59ade654d4 100644 --- a/policy/protocols/dns/base/main.bro +++ b/policy/protocols/dns/base/main.bro @@ -1,4 +1,3 @@ -@load protocols/dns/base/consts module DNS; diff --git a/policy/protocols/ssl/base.bro b/policy/protocols/ssl/base.bro index e046c3589e..7007566b7e 100644 --- a/policy/protocols/ssl/base.bro +++ b/policy/protocols/ssl/base.bro @@ -32,6 +32,11 @@ export { const root_certs: table[string] of string = {} &redef; global log_ssl: event(rec: Info); + + const ports = { + 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, + 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp + } &redef; } redef record connection += { @@ -57,13 +62,8 @@ redef capture_filters += { ["pop3s"] = "tcp port 995" }; -global ssl_ports = { - 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, - 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp -} &redef; - redef dpd_config += { - [[ANALYZER_SSL]] = [$ports = ssl_ports] + [[ANALYZER_SSL]] = [$ports = ports] }; function set_session(c: connection) diff --git a/policy/site/local.bro b/policy/site/local.bro index 85696c04e5..4a770af2cf 100644 --- a/policy/site/local.bro +++ b/policy/site/local.bro @@ -1,8 +1,10 @@ -##! Template for local site policy. Customize as appropriate. +##! Local site policy. Customize as appropriate. -# DPD should typically be loaded for detecting protocols on any port. +# DPD should typically be loaded. It enables the subsystem for detecting +# protocols on non-standard ports and attaching the appropriate analyzer. @load frameworks/dpd +# Load some of the commonly used frameworks. @load frameworks/notice @load frameworks/signatures @load frameworks/metrics @@ -14,7 +16,7 @@ @load frameworks/packet-filter/netstats @load misc/loaded-scripts - +# Load most of the protocol analysis scripts. @load protocols/conn @load protocols/dns @load protocols/ftp @@ -26,44 +28,5 @@ @load protocols/ssl @load protocols/syslog +# Apply the default tuning scripts for common tuning settings. @load tuning/defaults - -# Sample notice policy which you will almost certainly want -# to adapt to your environment. - -#redef notice_action_filters += -# { -# # These are all very common. -# #[Weird::ContentGap] = tally_notice_type_and_ignore, -# #[Weird::AckAboveHole] = tally_notice_type_and_ignore, -# #[Weird::RetransmissionInconsistency] = tally_notice_type_and_ignore, -# #[Drop::AddressDropIgnored] = ignore_notice, -# #[Drop::AddressDropped] = ignore_notice, -# #[Weird::WeirdActivity] = file_local_bro_notices, -# #[PacketFilter::DroppedPackets] = file_notice, -# #[TerminateConnection::TerminatingConnectionIgnored] = notice_alarm_per_orig, -# #[ProtocolDetector::ProtocolFound] = file_notice, -# #[ProtocolDetector::ServerFound] = file_if_remote, -# #[DynDisable::ProtocolViolation] = file_notice, -# }; - -redef Weird::weird_action += { - ["window_recision"] = Weird::WEIRD_FILE, - ["RST_with_data"] = Weird::WEIRD_FILE, - ["line_terminated_with_single_CR"] = Weird::WEIRD_FILE, - ["line_terminated_with_single_LF"] = Weird::WEIRD_FILE, - ["spontaneous_RST"] = Weird::WEIRD_FILE, - ["spontaneous_FIN"] = Weird::WEIRD_FILE, - ["data_before_established"] = Weird::WEIRD_FILE, - ["unsolicited_SYN_response"] = Weird::WEIRD_FILE, - ["inappropriate_FIN"] = Weird::WEIRD_FILE, - ["possible_split_routing"] = Weird::WEIRD_FILE, - ["connection_originator_SYN_ack"] = Weird::WEIRD_FILE, - ["fragment_inconsistency"] = Weird::WEIRD_NOTICE_PER_ORIG, - ["fragment_size_inconsistency"] = Weird::WEIRD_NOTICE_PER_ORIG, - ["fragment_overlap"] = Weird::WEIRD_NOTICE_PER_ORIG, - ["ICMP-unreachable for wrong state"] = Weird::WEIRD_NOTICE_PER_ORIG, - ["corrupt_tcp_options"] = Weird::WEIRD_NOTICE_PER_ORIG, -}; - - diff --git a/policy/tuning/defaults/__load__.bro b/policy/tuning/defaults/__load__.bro index ea235bf0b2..840c75d1de 100644 --- a/policy/tuning/defaults/__load__.bro +++ b/policy/tuning/defaults/__load__.bro @@ -1,2 +1,2 @@ -@load tuning/defaults/remove-high-volume-notices -@load tuning/defaults/packet-fragments \ No newline at end of file +@load ./remove-high-volume-notices +@load ./packet-fragments \ No newline at end of file diff --git a/policy/tuning/defaults/remove-high-volume-notices.bro b/policy/tuning/defaults/remove-high-volume-notices.bro index 7fd0c08edc..0dc58e278a 100644 --- a/policy/tuning/defaults/remove-high-volume-notices.bro +++ b/policy/tuning/defaults/remove-high-volume-notices.bro @@ -1,12 +1,13 @@ ##! This strives to tune out high volume and less useful data ##! from the notice log. -@load frameworks/notice - # Remove these notices from logging since they can be too noisy. redef Notice::ignored_types += { Weird::ContentGap, Weird::AckAboveHole, Weird::RetransmissionInconsistency, - Weird::WeirdActivity, # Only allow these to go in the weird log. + ## Only allow these to go in the weird log. + Weird::WeirdActivity, + #DynDisable::ProtocolViolation, + }; \ No newline at end of file