diff --git a/CHANGES b/CHANGES index 160ec42f8b..c84410303b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,12 @@ +2.3-636 | 2015-03-30 11:26:32 -0500 + + * Updates related to SSH analysis. (Jon Siwek) + + - Some scripts used wrong SSH module/namespace scoping on events. + - Fix outdated notice documentation related to SSH password guessing. + - Add a unit test for SSH pasword guessing notice. + 2.3-635 | 2015-03-30 11:02:45 -0500 * Fix outdated documentation unit tests. (Jon Siwek) diff --git a/NEWS b/NEWS index 6767537170..a0248d4966 100644 --- a/NEWS +++ b/NEWS @@ -30,7 +30,7 @@ New Functionality - Bro now features a completely rewritten, enhanced SSH analyzer. A lot more information about SSH sessions is logged. The analyzer is able to - determine if logins failed or succeeded in most circumstances. + determine if logins failed or succeeded in most circumstances. - Bro's file analysis now supports reassembly of files that are not transferred/seen sequentially. @@ -123,6 +123,8 @@ Changed Functionality explicitly set. Before, the default path function would always be set for all filters which didn't specify their own ``path_func``. +- TODO: what SSH events got changed or removed? + Deprecated Functionality ------------------------ diff --git a/VERSION b/VERSION index 49259bdc23..b7ffdd164c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3-635 +2.3-636 diff --git a/doc/frameworks/notice.rst b/doc/frameworks/notice.rst index d8197c13af..eacf9c917f 100644 --- a/doc/frameworks/notice.rst +++ b/doc/frameworks/notice.rst @@ -88,15 +88,15 @@ directly make modifications to the :bro:see:`Notice::Info` record given as the argument to the hook. Here's a simple example which tells Bro to send an email for all notices of -type :bro:see:`SSH::Password_Guessing` if the server is 10.0.0.1: +type :bro:see:`SSH::Password_Guessing` if the guesser attempted to log in to +the server at 192.168.56.103: -.. code:: bro +.. btest-include:: ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro - hook Notice::policy(n: Notice::Info) - { - if ( n$note == SSH::Password_Guessing && n$id$resp_h == 10.0.0.1 ) - add n$actions[Notice::ACTION_EMAIL]; - } +.. btest:: notice_ssh_guesser.bro + + @TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro + @TEST-EXEC: btest-rst-cmd cat notice.log .. note:: @@ -111,10 +111,9 @@ a hook body to run before default hook bodies might look like this: .. code:: bro hook Notice::policy(n: Notice::Info) &priority=5 - { - if ( n$note == SSH::Password_Guessing && n$id$resp_h == 10.0.0.1 ) - add n$actions[Notice::ACTION_EMAIL]; - } + { + # Insert your code here. + } Hooks can also abort later hook bodies with the ``break`` keyword. This is primarily useful if one wants to completely preempt processing by diff --git a/doc/frameworks/notice_ssh_guesser.bro b/doc/frameworks/notice_ssh_guesser.bro new file mode 100644 index 0000000000..34ffe2e95e --- /dev/null +++ b/doc/frameworks/notice_ssh_guesser.bro @@ -0,0 +1,10 @@ + +@load protocols/ssh/detect-bruteforcing + +redef SSH::password_guesses_limit=10; + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Password_Guessing && /192\.168\.56\.103/ in n$sub ) + add n$actions[Notice::ACTION_EMAIL]; + } diff --git a/scripts/base/protocols/ssh/main.bro b/scripts/base/protocols/ssh/main.bro index 42c323601c..a64a4a0e21 100644 --- a/scripts/base/protocols/ssh/main.bro +++ b/scripts/base/protocols/ssh/main.bro @@ -57,8 +57,8 @@ export { global log_ssh: event(rec: Info); ## Event that can be handled when the analyzer sees an SSH server host - ## key. This abstracts :bro:id:`SSH::ssh1_server_host_key` and - ## :bro:id:`SSH::ssh2_server_host_key`. + ## key. This abstracts :bro:id:`ssh1_server_host_key` and + ## :bro:id:`ssh2_server_host_key`. global ssh_server_host_key: event(c: connection, hash: string); } diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index f0c76ec904..55687e2afd 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -69,7 +69,7 @@ event bro_init() }]); } -event SSH::ssh_auth_successful(c: connection, auth_method_none: bool) +event ssh_auth_successful(c: connection, auth_method_none: bool) { local id = c$id; @@ -78,7 +78,7 @@ event SSH::ssh_auth_successful(c: connection, auth_method_none: bool) $where=SSH::SUCCESSFUL_LOGIN]); } -event SSH::ssh_auth_failed(c: connection) +event ssh_auth_failed(c: connection) { local id = c$id; diff --git a/scripts/policy/protocols/ssh/geo-data.bro b/scripts/policy/protocols/ssh/geo-data.bro index 00b52058a1..feae86c8f6 100644 --- a/scripts/policy/protocols/ssh/geo-data.bro +++ b/scripts/policy/protocols/ssh/geo-data.bro @@ -30,7 +30,7 @@ function get_location(c: connection): geo_location return lookup_location(lookup_ip); } -event SSH::ssh_auth_successful(c: connection, auth_method_none: bool) &priority=3 +event ssh_auth_successful(c: connection, auth_method_none: bool) &priority=3 { # Add the location data to the SSH record. c$ssh$remote_location = get_location(c); @@ -45,7 +45,7 @@ event SSH::ssh_auth_successful(c: connection, auth_method_none: bool) &priority= } } -event SSH::ssh_auth_failed(c: connection) &priority=3 +event ssh_auth_failed(c: connection) &priority=3 { # Add the location data to the SSH record. c$ssh$remote_location = get_location(c); diff --git a/scripts/policy/protocols/ssh/interesting-hostnames.bro b/scripts/policy/protocols/ssh/interesting-hostnames.bro index e43349c030..af6f441646 100644 --- a/scripts/policy/protocols/ssh/interesting-hostnames.bro +++ b/scripts/policy/protocols/ssh/interesting-hostnames.bro @@ -27,7 +27,7 @@ export { /^ftp[0-9]*\./ &redef; } -event SSH::ssh_auth_successful(c: connection, auth_method_none: bool) +event ssh_auth_successful(c: connection, auth_method_none: bool) { for ( host in set(c$id$orig_h, c$id$resp_h) ) { diff --git a/testing/btest/Baseline/doc.sphinx.include-doc_frameworks_notice_ssh_guesser_bro/output b/testing/btest/Baseline/doc.sphinx.include-doc_frameworks_notice_ssh_guesser_bro/output new file mode 100644 index 0000000000..11b77dd1ba --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.include-doc_frameworks_notice_ssh_guesser_bro/output @@ -0,0 +1,14 @@ +# @TEST-EXEC: cat %INPUT >output && btest-diff output + +notice_ssh_guesser.bro + + +@load protocols/ssh/detect-bruteforcing + +redef SSH::password_guesses_limit=10; + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Password_Guessing && /192\.168\.56\.103/ in n$sub ) + add n$actions[Notice::ACTION_EMAIL]; + } diff --git a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output index af9ea0dc83..7905ffd953 100644 --- a/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output +++ b/testing/btest/Baseline/doc.sphinx.include-scripts_policy_protocols_ssh_interesting-hostnames_bro/output @@ -31,7 +31,7 @@ export { /^ftp[0-9]*\./ &redef; } -event SSH::heuristic_successful_login(c: connection) +event ssh_auth_successful(c: connection, auth_method_none: bool) { for ( host in set(c$id$orig_h, c$id$resp_h) ) { diff --git a/testing/btest/Baseline/doc.sphinx.notice_ssh_guesser.bro/btest-doc.sphinx.notice_ssh_guesser.bro#1 b/testing/btest/Baseline/doc.sphinx.notice_ssh_guesser.bro/btest-doc.sphinx.notice_ssh_guesser.bro#1 new file mode 100644 index 0000000000..a8d9ce96d1 --- /dev/null +++ b/testing/btest/Baseline/doc.sphinx.notice_ssh_guesser.bro/btest-doc.sphinx.notice_ssh_guesser.bro#1 @@ -0,0 +1,26 @@ +.. rst-class:: btest-cmd + + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # bro -C -r ssh/sshguess.pcap notice_ssh_guesser.bro + +.. rst-class:: btest-cmd + + .. code-block:: none + :linenos: + :emphasize-lines: 1,1 + + # cat notice.log + #separator \x09 + #set_separator , + #empty_field (empty) + #unset_field - + #path notice + #open 2015-03-30-16-20-23 + #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude + #types time string addr port addr port string string string enum enum string string addr addr port count string set[enum] interval bool string string string double double + 1427726711.398575 - - - - - - - - - SSH::Password_Guessing 192.168.56.1 appears to be guessing SSH passwords (seen in 10 connections). Sampled servers: 192.168.56.103, 192.168.56.103, 192.168.56.103, 192.168.56.103, 192.168.56.103 192.168.56.1 - - - bro Notice::ACTION_EMAIL,Notice::ACTION_LOG 3600.000000 F - - - - - + #close 2015-03-30-16-20-23 + diff --git a/testing/btest/Baseline/scripts.policy.protocols.ssh.detect-bruteforcing/notice.log b/testing/btest/Baseline/scripts.policy.protocols.ssh.detect-bruteforcing/notice.log new file mode 100644 index 0000000000..ee206db117 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.ssh.detect-bruteforcing/notice.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path notice +#open 2015-03-30-15-43-30 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude +#types time string addr port addr port string string string enum enum string string addr addr port count string set[enum] interval bool string string string double double +1427726711.398575 - - - - - - - - - SSH::Password_Guessing 192.168.56.1 appears to be guessing SSH passwords (seen in 10 connections). Sampled servers: 192.168.56.103, 192.168.56.103, 192.168.56.103, 192.168.56.103, 192.168.56.103 192.168.56.1 - - - bro Notice::ACTION_LOG 3600.000000 F - - - - - +#close 2015-03-30-15-43-30 diff --git a/testing/btest/Traces/ssh/sshguess.pcap b/testing/btest/Traces/ssh/sshguess.pcap new file mode 100644 index 0000000000..7408acc948 Binary files /dev/null and b/testing/btest/Traces/ssh/sshguess.pcap differ diff --git a/testing/btest/doc/sphinx/include-doc_frameworks_notice_ssh_guesser_bro.btest b/testing/btest/doc/sphinx/include-doc_frameworks_notice_ssh_guesser_bro.btest new file mode 100644 index 0000000000..11b77dd1ba --- /dev/null +++ b/testing/btest/doc/sphinx/include-doc_frameworks_notice_ssh_guesser_bro.btest @@ -0,0 +1,14 @@ +# @TEST-EXEC: cat %INPUT >output && btest-diff output + +notice_ssh_guesser.bro + + +@load protocols/ssh/detect-bruteforcing + +redef SSH::password_guesses_limit=10; + +hook Notice::policy(n: Notice::Info) + { + if ( n$note == SSH::Password_Guessing && /192\.168\.56\.103/ in n$sub ) + add n$actions[Notice::ACTION_EMAIL]; + } diff --git a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest index af9ea0dc83..7905ffd953 100644 --- a/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest +++ b/testing/btest/doc/sphinx/include-scripts_policy_protocols_ssh_interesting-hostnames_bro.btest @@ -31,7 +31,7 @@ export { /^ftp[0-9]*\./ &redef; } -event SSH::heuristic_successful_login(c: connection) +event ssh_auth_successful(c: connection, auth_method_none: bool) { for ( host in set(c$id$orig_h, c$id$resp_h) ) { diff --git a/testing/btest/doc/sphinx/notice_ssh_guesser.bro.btest b/testing/btest/doc/sphinx/notice_ssh_guesser.bro.btest new file mode 100644 index 0000000000..50d6f17694 --- /dev/null +++ b/testing/btest/doc/sphinx/notice_ssh_guesser.bro.btest @@ -0,0 +1,2 @@ +@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro +@TEST-EXEC: btest-rst-cmd cat notice.log diff --git a/testing/btest/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/testing/btest/scripts/policy/protocols/ssh/detect-bruteforcing.bro new file mode 100644 index 0000000000..e28ebf5b49 --- /dev/null +++ b/testing/btest/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -0,0 +1,5 @@ +# @TEST-EXEC: bro -C -r $TRACES/ssh/sshguess.pcap %INPUT +# @TEST-EXEC: btest-diff notice.log + +@load protocols/ssh/detect-bruteforcing +redef SSH::password_guesses_limit=10;