diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index f20495deb5..2026f9bfa2 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -493,40 +493,41 @@ export { } &default="UNKNOWN"; const x509_errors: table[count] of string = { - [0] = "X509_V_OK", - [1] = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", - [2] = "X509_V_ERR_UNABLE_TO_GET_CRL", - [3] = "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE", - [4] = "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE", - [5] = "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", - [6] = "X509_V_ERR_CERT_SIGNATURE_FAILURE", - [7] = "X509_V_ERR_CRL_SIGNATURE_FAILURE", - [8] = "X509_V_ERR_CERT_NOT_YET_VALID", - [9] = "X509_V_ERR_CERT_HAS_EXPIRED", - [10] = "X509_V_ERR_CRL_NOT_YET_VALID", - [11] = "X509_V_ERR_CRL_HAS_EXPIRED", - [12] = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", - [13] = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", - [14] = "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD", - [15] = "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD", - [16] = "X509_V_ERR_OUT_OF_MEM", - [17] = "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT", - [18] = "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN", - [19] = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", - [20] = "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE", - [21] = "X509_V_ERR_CERT_CHAIN_TOO_LONG", - [22] = "X509_V_ERR_CERT_REVOKED", - [23] = "X509_V_ERR_INVALID_CA", - [24] = "X509_V_ERR_PATH_LENGTH_EXCEEDED", - [25] = "X509_V_ERR_INVALID_PURPOSE", - [26] = "X509_V_ERR_CERT_UNTRUSTED", - [27] = "X509_V_ERR_CERT_REJECTED", - [28] = "X509_V_ERR_SUBJECT_ISSUER_MISMATCH", - [29] = "X509_V_ERR_AKID_SKID_MISMATCH", - [30] = "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH", - [31] = "X509_V_ERR_KEYUSAGE_NO_CERTSIGN", - [32] = "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER", - [33] = "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION" + [0] = "ok", + [1] = "unable to get issuer cert", + [2] = "unable to get crl", + [3] = "unable to decrypt cert signature", + [4] = "unable to decrypt crl signature", + [5] = "unable to decode issuer public key", + [6] = "cert signature failure", + [7] = "crl signature failure", + [8] = "cert not yet valid", + [9] = "cert has expired", + [10] = "crl not yet valid", + [11] = "crl has expired", + [12] = "error in cert not before field", + [13] = "error in cert not after field", + [14] = "error in crl last update field", + [15] = "error in crl next update field", + [16] = "out of mem", + [17] = "depth zero self signed cert", + [18] = "self signed cert in chain", + [19] = "unable to get issuer cert locally", + [20] = "unable to verify leaf signature", + [21] = "cert chain too long", + [22] = "cert revoked", + [23] = "invalid ca", + [24] = "path length exceeded", + [25] = "invalid purpose", + [26] = "cert untrusted", + [27] = "cert rejected", + [28] = "subject issuer mismatch", + [29] = "akid skid mismatch", + [30] = "akid issuer serial mismatch", + [31] = "keyusage no certsign", + [32] = "unable to get crl issuer", + [33] = "unhandled critical extension" + }; } diff --git a/scripts/policy/misc/loaded-scripts.bro b/scripts/policy/misc/loaded-scripts.bro index 7dd7025689..27275156ea 100644 --- a/scripts/policy/misc/loaded-scripts.bro +++ b/scripts/policy/misc/loaded-scripts.bro @@ -1,10 +1,15 @@ +##! + module LoadedScripts; export { redef enum Log::ID += { LOG }; type Info: record { - name: string &log; + ## Name of the script loaded potentially with spaces included before + ## the file name to indicate load depth. The convention is two spaces + ## per level of depth. + name: string &log; }; } diff --git a/scripts/policy/protocols/conn/known-services.bro b/scripts/policy/protocols/conn/known-services.bro index c2343157dc..557fe35fb2 100644 --- a/scripts/policy/protocols/conn/known-services.bro +++ b/scripts/policy/protocols/conn/known-services.bro @@ -29,6 +29,8 @@ export { } redef record connection += { + ## This field is to indicate whether or not the processing for detecting + ## and logging the service for this connection is complete. known_services_done: bool &default=F; }; diff --git a/scripts/policy/protocols/conn/weirds.bro b/scripts/policy/protocols/conn/weirds.bro index a4db61e51f..9d6730819c 100644 --- a/scripts/policy/protocols/conn/weirds.bro +++ b/scripts/policy/protocols/conn/weirds.bro @@ -1,11 +1,12 @@ ##! This script handles core generated connection related "weird" events to ##! push weird information about connections into the weird framework. ##! For live operational deployments, this can frequently cause load issues -##! due to large numbers of these events being passed between nodes. +##! due to large numbers of these events and quite possibly shouldn't be +##! loaded. @load base/frameworks/notice -module Weird; +module Conn; export { redef enum Notice::Type += { @@ -20,14 +21,11 @@ export { event rexmit_inconsistency(c: connection, t1: string, t2: string) { - if ( c$id !in did_inconsistency_msg ) - { - NOTICE([$note=Retransmission_Inconsistency, - $conn=c, - $msg=fmt("%s rexmit inconsistency (%s) (%s)", - id_string(c$id), t1, t2)]); - add did_inconsistency_msg[c$id]; - } + NOTICE([$note=Retransmission_Inconsistency, + $conn=c, + $msg=fmt("%s rexmit inconsistency (%s) (%s)", + id_string(c$id), t1, t2), + $identifier=fmt("%s", c$id)]); } event ack_above_hole(c: connection) diff --git a/scripts/policy/protocols/dns/auth-addl.bro b/scripts/policy/protocols/dns/auth-addl.bro index dd00e59c2e..8c04379c1c 100644 --- a/scripts/policy/protocols/dns/auth-addl.bro +++ b/scripts/policy/protocols/dns/auth-addl.bro @@ -1,3 +1,8 @@ +##! This script adds authoritative and additional responses for the current +##! query to the DNS log. It can cause severe overhead due to the need +##! for all authoritative and additional responses to have events generated. +##! This script is not recommended for use on heavily loaded links. + @load base/protocols/dns/main redef dns_skip_all_auth = F; @@ -7,12 +12,14 @@ module DNS; export { redef record Info += { + ## Authoritative responses for the query. auth: set[string] &log &optional; + ## Additional responses for the query. addl: set[string] &log &optional; }; } -event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=4 +event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=4 { # The "ready" flag will be set here. This causes the setting from the # base script to be overridden since the base script will log immediately diff --git a/scripts/policy/protocols/dns/detect-external-names.bro b/scripts/policy/protocols/dns/detect-external-names.bro index f6f0e596cc..a1897d06e7 100644 --- a/scripts/policy/protocols/dns/detect-external-names.bro +++ b/scripts/policy/protocols/dns/detect-external-names.bro @@ -1,14 +1,9 @@ -##! Script for detecting strange activity within DNS. -##! -##! Notices raised: -##! -##! * :bro:enum:`DNS::External_Name` -##! -##! A remote host resolves to a local host, but the name is not considered -##! to be within a local zone. :bro:id:`local_zones` variable **must** -##! be set appropriately for this detection. +##! This script detects names which are not within zones considered to be +##! local but resolving to addresses considered local. +##! The :bro:id:`Site::local_zones` variable **must** be set appropriately for +##! this detection. -@load base/frameworks/notice/main +@load base/frameworks/notice @load base/utils/site module DNS; @@ -16,8 +11,8 @@ module DNS; export { redef enum Notice::Type += { ## Raised when a non-local name is found to be pointing at a local host. - ## This only works appropriately when all of your authoritative DNS - ## servers are located in your :bro:id:`Site::local_nets`. + ## :bro:id:`Site::local_zones` variable **must** be set appropriately + ## for this detection. External_Name, }; } @@ -30,11 +25,11 @@ event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priori # Check for responses from remote hosts that point at local hosts # but the name is not considered to be within a "local" zone. if ( Site::is_local_addr(a) && # referring to a local host - !Site::is_local_addr(c$id$resp_h) && # response from an external nameserver - !Site::is_local_name(ans$query) ) # name isn't in a local zone. + ! Site::is_local_name(ans$query) ) # name isn't in a local zone. { NOTICE([$note=External_Name, $msg=fmt("%s is pointing to a local host - %s.", ans$query, a), - $conn=c]); + $conn=c, + $identifier=cat(a,ans$query)]); } } diff --git a/scripts/policy/protocols/ftp/detect.bro b/scripts/policy/protocols/ftp/detect.bro index cb89599a93..abb62e08fc 100644 --- a/scripts/policy/protocols/ftp/detect.bro +++ b/scripts/policy/protocols/ftp/detect.bro @@ -1,5 +1,7 @@ -@load base/frameworks/notice/main -@load base/protocols/ftp/main +##! Detect various potentially bad FTP activities. + +@load base/frameworks/notice +@load base/protocols/ftp module FTP; @@ -21,6 +23,7 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior /[Ee][Xx][Ee][Cc]/ in c$ftp$cmdarg$arg ) { NOTICE([$note=Site_Exec_Success, $conn=c, - $msg=fmt("%s %s", c$ftp$cmdarg$cmd, c$ftp$cmdarg$arg)]); + $msg=fmt("FTP command: %s %s", c$ftp$cmdarg$cmd, c$ftp$cmdarg$arg), + $identifier=cat(c$id$orig_h, c$id$resp_h, "SITE EXEC")]); } } diff --git a/scripts/policy/protocols/ftp/software.bro b/scripts/policy/protocols/ftp/software.bro index 7dfd54ddca..622357a608 100644 --- a/scripts/policy/protocols/ftp/software.bro +++ b/scripts/policy/protocols/ftp/software.bro @@ -1,12 +1,12 @@ ##! Software detection with the FTP protocol. -##! -##! TODO: -##! -##! * Detect server software with initial 220 message -##! * Detect client software with password given for anonymous users -##! (e.g. cyberduck@example.net) -@load base/frameworks/software/main +# TODO: +# +# * Detect server software with initial 220 message +# * Detect client software with password given for anonymous users +# (e.g. cyberduck@example.net) + +@load base/frameworks/software module FTP; diff --git a/scripts/policy/protocols/http/detect-MHR.bro b/scripts/policy/protocols/http/detect-MHR.bro index 7b99184a9b..3b2e8bf968 100644 --- a/scripts/policy/protocols/http/detect-MHR.bro +++ b/scripts/policy/protocols/http/detect-MHR.bro @@ -4,10 +4,8 @@ ##! documentation for the :doc:base/protocols/http/file-hash.bro script to see how to ##! configure which transfers will have hashes calculated. -@load base/frameworks/notice/main -@load base/protocols/http/main -@load base/protocols/http/utils -@load base/protocols/http/file-hash +@load base/frameworks/notice +@load base/protocols/http export { redef enum Notice::Type += { diff --git a/scripts/policy/protocols/http/detect-sqli.bro b/scripts/policy/protocols/http/detect-sqli.bro index 89a37728f4..c4ba7ee74e 100644 --- a/scripts/policy/protocols/http/detect-sqli.bro +++ b/scripts/policy/protocols/http/detect-sqli.bro @@ -1,4 +1,4 @@ -##! SQL injection detection in HTTP. +##! SQL injection attack detection in HTTP. @load base/frameworks/notice @load base/frameworks/metrics @@ -8,7 +8,10 @@ module HTTP; export { redef enum Notice::Type += { + ## Indicates that a host performing SQL injection attacks was detected. SQL_Injection_Attacker, + ## Indicates that a host was seen to have SQL injection attacks against + ## it. This is tracked by IP address as opposed to hostname. SQL_Injection_Attack_Against, }; @@ -49,9 +52,13 @@ export { event bro_init() &priority=3 { + # Add filters to the metrics so that the metrics framework knows how to + # determine when it looks like an actual attack and how to respond when + # thresholds are crossed. + Metrics::add_filter(SQL_ATTACKER, [$log=F, $notice_threshold=sqli_requests_threshold, - $break_interval=sqli_requests_interval, + $break_interval=sqli_requests_interval, $note=SQL_Injection_Attacker]); Metrics::add_filter(SQL_ATTACKS_AGAINST, [$log=F, $notice_threshold=sqli_requests_threshold, diff --git a/scripts/policy/protocols/http/detect-webapps.bro b/scripts/policy/protocols/http/detect-webapps.bro index 493ea9b44b..4a94d1adbd 100644 --- a/scripts/policy/protocols/http/detect-webapps.bro +++ b/scripts/policy/protocols/http/detect-webapps.bro @@ -1,7 +1,6 @@ -@load base/frameworks/signatures/main -@load base/frameworks/software/main -@load base/protocols/http/main -@load base/protocols/http/utils +@load base/frameworks/signatures +@load base/frameworks/software +@load base/protocols/http module HTTP; diff --git a/scripts/policy/protocols/http/software-browser-plugins.bro b/scripts/policy/protocols/http/software-browser-plugins.bro index 51d452cf5f..db9eafd1a7 100644 --- a/scripts/policy/protocols/http/software-browser-plugins.bro +++ b/scripts/policy/protocols/http/software-browser-plugins.bro @@ -1,5 +1,6 @@ ##! This script take advantage of a few ways that installed plugin information -##! leaks from web browsers +##! leaks from web browsers. + @load base/protocols/http @load base/frameworks/software diff --git a/scripts/policy/protocols/http/software.bro b/scripts/policy/protocols/http/software.bro index f45d4d7542..8732634359 100644 --- a/scripts/policy/protocols/http/software.bro +++ b/scripts/policy/protocols/http/software.bro @@ -1,6 +1,6 @@ ##! Software identification and extraction for HTTP traffic. -@load base/frameworks/software/main +@load base/frameworks/software module HTTP; diff --git a/scripts/policy/protocols/http/var-extraction-uri.bro b/scripts/policy/protocols/http/var-extraction-uri.bro index 32ea147961..b03474bb94 100644 --- a/scripts/policy/protocols/http/var-extraction-uri.bro +++ b/scripts/policy/protocols/http/var-extraction-uri.bro @@ -1,7 +1,6 @@ ##! This script extracts and logs variables from the requested URI -@load base/protocols/http/main -@load base/protocols/http/utils +@load base/protocols/http module HTTP; diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index 1bed741da2..3abe185d58 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -38,7 +38,8 @@ export { const ignore_guessers: table[subnet] of subnet &redef; ## Keeps track of hosts identified as guessing passwords. - global password_guessers: set[addr] &read_expire=guessing_timeout+1hr &synchronized; + global password_guessers: set[addr] + &read_expire=guessing_timeout+1hr &synchronized &redef; } event bro_init() diff --git a/scripts/policy/protocols/ssh/geo-data.bro b/scripts/policy/protocols/ssh/geo-data.bro index 1ac38e5a5b..daa05f4ebc 100644 --- a/scripts/policy/protocols/ssh/geo-data.bro +++ b/scripts/policy/protocols/ssh/geo-data.bro @@ -1,8 +1,8 @@ ##! This implements all of the additional information and geodata detections ##! for SSH analysis. -@load base/frameworks/notice/main -@load base/protocols/ssh/main +@load base/frameworks/notice +@load base/protocols/ssh module SSH; @@ -11,17 +11,17 @@ export { ## If an SSH login is seen to or from a "watched" country based on the ## :bro:id:`SSH::watched_countries` variable then this notice will ## be generated. - Login_From_Watched_Country, + Watched_Country_Login, + }; + + redef record Info += { + ## Add geographic data related to the "remote" host of the connection. + remote_location: geo_location &log &optional; }; ## The set of countries for which you'd like to throw notices upon ## successful login const watched_countries: set[string] = {"RO"} &redef; - - redef record Info += { - ## Add geographic data related to the "remote" host of the connection. - remote_location: geo_location &log &optional; - }; } event SSH::heuristic_successful_login(c: connection) &priority=5 @@ -35,8 +35,10 @@ event SSH::heuristic_successful_login(c: connection) &priority=5 if ( location?$country_code && location$country_code in watched_countries ) { - NOTICE([$note=Login_From_Watched_Country, + NOTICE([$note=Watched_Country_Login, $conn=c, - $msg=fmt("SSH login from watched country: %s", location$country_code)]); + $msg=fmt("SSH login %s watched country: %s", + (c$ssh$direction == OUTBOUND) ? "to" : "from", + location$country_code)]); } } diff --git a/scripts/policy/protocols/ssh/software.bro b/scripts/policy/protocols/ssh/software.bro index d9bfdffb3c..a239655270 100644 --- a/scripts/policy/protocols/ssh/software.bro +++ b/scripts/policy/protocols/ssh/software.bro @@ -1,4 +1,7 @@ -@load base/frameworks/software/main +##! This script extracts SSH client and server information from SSH +##! connections and forwards it to the software framework. + +@load base/frameworks/software module SSH; diff --git a/scripts/policy/protocols/ssl/validate-certs.bro b/scripts/policy/protocols/ssl/validate-certs.bro index f9294ed650..5a663864d2 100644 --- a/scripts/policy/protocols/ssl/validate-certs.bro +++ b/scripts/policy/protocols/ssl/validate-certs.bro @@ -1,26 +1,29 @@ ##! Perform full certificate chain validation for SSL certificates. -@load base/frameworks/notice/main -@load base/protocols/ssl/main - +@load base/frameworks/notice +@load base/protocols/ssl @load protocols/ssl/cert-hash module SSL; export { redef enum Notice::Type += { + ## This notice indicates that the result of validating the certificate + ## along with it's full certificate chain was invalid. Invalid_Server_Cert }; redef record Info += { + ## This stores and logs the result of certificate validation for + ## this connection. validation_status: string &log &optional; }; ## MD5 hash values for recently validated certs along with the validation - ## status message are kept in this table so avoid constant validation + ## status message are kept in this table to avoid constant validation ## everytime the same certificate is seen. global recently_validated_certs: table[string] of string = table() - &read_expire=5mins &synchronized; + &read_expire=5mins &synchronized &redef; } event ssl_established(c: connection) &priority=3