Remove Sphinx btest integrations and tests

This commit is contained in:
Jon Siwek 2018-12-14 16:32:35 -06:00
parent be0d3021fa
commit 9e5e9d04b7
294 changed files with 1215 additions and 5590 deletions

View file

@ -23,13 +23,14 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/broxygen.conf.in
${CMAKE_CURRENT_BINARY_DIR}/broxygen.conf ${CMAKE_CURRENT_BINARY_DIR}/broxygen.conf
@ONLY) @ONLY)
add_custom_target(sphinxdoc add_custom_target(rstdoc
# Copy the template documentation to build directory to use as input tree # Copy the template documentation to build directory to use as input tree
# for Sphinx. This is needed because some parts are dynamically generated # for Sphinx. This is needed because some parts are dynamically generated
# in to that tree by Bro/Broxygen. # in to that tree by Bro/Broxygen.
COMMAND rsync -q -r --copy-links --times --delete COMMAND rsync -q -r --copy-links --times --delete
--filter='protect scripts/*' --filter='protect scripts/*'
${CMAKE_CURRENT_SOURCE_DIR}/ ${SPHINX_INPUT_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/
${SPHINX_INPUT_DIR}
# Use Bro/Broxygen to dynamically generate reST for all Bro scripts. # Use Bro/Broxygen to dynamically generate reST for all Bro scripts.
COMMAND BROPATH=${BROPATH} COMMAND BROPATH=${BROPATH}
${CMAKE_BINARY_DIR}/src/bro ${CMAKE_BINARY_DIR}/src/bro
@ -37,19 +38,26 @@ add_custom_target(sphinxdoc
broxygen >/dev/null broxygen >/dev/null
# Rsync over the generated reST to the Sphinx source tree in the build dir. # Rsync over the generated reST to the Sphinx source tree in the build dir.
COMMAND rsync -q -r --copy-links --times --delete --filter='protect *.bro' COMMAND rsync -q -r --copy-links --times --delete --filter='protect *.bro'
${BROXYGEN_SCRIPT_OUTPUT}/ ${SPHINX_INPUT_DIR}/scripts ${BROXYGEN_SCRIPT_OUTPUT}/
${SPHINX_INPUT_DIR}/scripts
# Rsync over Bro scripts to the Sphinx source tree in the build dir. # Rsync over Bro scripts to the Sphinx source tree in the build dir.
# These are used by :download: references in the generated script docs. # These are used by :download: references in the generated script docs.
COMMAND rsync -q -r --copy-links --times --delete COMMAND rsync -q -r --copy-links --times --delete
--filter='protect /base/bif/*' --filter='protect *.rst' --filter='protect /base/bif/*' --filter='protect *.rst'
--filter='include */' --filter='include *.bro' --filter='exclude *' --filter='include */' --filter='include *.bro' --filter='exclude *'
${CMAKE_SOURCE_DIR}/scripts/ ${SPHINX_INPUT_DIR}/scripts ${CMAKE_SOURCE_DIR}/scripts/
${SPHINX_INPUT_DIR}/scripts
# Rsync over Bro scripts created by BIF compiler to the Sphinx source tree. # Rsync over Bro scripts created by BIF compiler to the Sphinx source tree.
COMMAND rsync -q -r --copy-links --times --delete COMMAND rsync -q -r --copy-links --times --delete
--filter='protect *.rst' --filter='include */' --filter='protect *.rst' --filter='include */'
--filter='include *.bro' --filter='exclude *' --filter='include *.bro' --filter='exclude *'
${CMAKE_BINARY_DIR}/scripts/base/bif/ ${CMAKE_BINARY_DIR}/scripts/base/bif/
${SPHINX_INPUT_DIR}/scripts/base/bif ${SPHINX_INPUT_DIR}/scripts/base/bif
)
add_dependencies(rstdoc bro)
add_custom_target(sphinxdoc
# Use Sphinx to build HTML. # Use Sphinx to build HTML.
COMMAND sphinx-build COMMAND sphinx-build
-b html -b html
@ -64,19 +72,21 @@ add_custom_target(sphinxdoc
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "[Sphinx] Generate HTML documentation in ${CMAKE_BINARY_DIR}/html") COMMENT "[Sphinx] Generate HTML documentation in ${CMAKE_BINARY_DIR}/html")
add_dependencies(sphinxdoc bro) add_dependencies(sphinxdoc rstdoc)
add_custom_target(sphinxdoc_clean add_custom_target(rstdoc_clean
COMMAND "${CMAKE_COMMAND}" -E remove_directory ${SPHINX_INPUT_DIR} COMMAND "${CMAKE_COMMAND}" -E remove_directory ${SPHINX_INPUT_DIR}
COMMAND "${CMAKE_COMMAND}" -E remove_directory ${SPHINX_OUTPUT_DIR}
COMMAND "${CMAKE_COMMAND}" -E remove_directory ${BROXYGEN_SCRIPT_OUTPUT} COMMAND "${CMAKE_COMMAND}" -E remove_directory ${BROXYGEN_SCRIPT_OUTPUT}
COMMAND "${CMAKE_COMMAND}" -E remove_directory ${BROXYGEN_CACHE_DIR} COMMAND "${CMAKE_COMMAND}" -E remove_directory ${BROXYGEN_CACHE_DIR}
VERBATIM) VERBATIM)
add_custom_target(sphinxdoc_clean
COMMAND "${CMAKE_COMMAND}" -E remove_directory ${SPHINX_OUTPUT_DIR})
if (NOT TARGET doc) if (NOT TARGET doc)
add_custom_target(doc) add_custom_target(doc)
endif () endif ()
add_custom_target(docclean) add_custom_target(docclean)
add_dependencies(doc sphinxdoc) add_dependencies(doc sphinxdoc)
add_dependencies(docclean sphinxdoc_clean) add_dependencies(docclean sphinxdoc_clean rstdoc_clean)

View file

@ -24,8 +24,26 @@ rejected usernames and passwords occurring from a single address. We
start by defining a threshold for the number of attempts, a monitoring start by defining a threshold for the number of attempts, a monitoring
interval (in minutes), and a new notice type. interval (in minutes), and a new notice type.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ftp/detect-bruteforcing.bro .. code-block:: bro
:lines: 9-25 :caption: detect-bruteforcing.bro
module FTP;
export {
redef enum Notice::Type += {
## Indicates a host bruteforcing FTP logins by watching for too
## many rejected usernames or failed passwords.
Bruteforcing
};
## How many rejected usernames or passwords are required before being
## considered to be bruteforcing.
const bruteforce_threshold: double = 20 &redef;
## The time period in which the threshold needs to be crossed before
## being reset.
const bruteforce_measurement_interval = 15mins &redef;
}
Using the ftp_reply event, we check for error codes from the `500 Using the ftp_reply event, we check for error codes from the `500
series <http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes>`_ series <http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes>`_
@ -35,24 +53,130 @@ function to break down the reply code and check if the first digit is a
"5" or not. If true, we then use the :ref:`Summary Statistics Framework "5" or not. If true, we then use the :ref:`Summary Statistics Framework
<sumstats-framework>` to keep track of the number of failed attempts. <sumstats-framework>` to keep track of the number of failed attempts.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ftp/detect-bruteforcing.bro .. code-block:: bro
:lines: 52-60 :caption: detect-bruteforcing.bro
event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool)
{
local cmd = c$ftp$cmdarg$cmd;
if ( cmd == "USER" || cmd == "PASS" )
{
if ( FTP::parse_ftp_reply_code(code)$x == 5 )
SumStats::observe("ftp.failed_auth", [$host=c$id$orig_h], [$str=cat(c$id$resp_h)]);
}
}
Next, we use the SumStats framework to raise a notice of the attack when Next, we use the SumStats framework to raise a notice of the attack when
the number of failed attempts exceeds the specified threshold during the the number of failed attempts exceeds the specified threshold during the
measuring interval. measuring interval.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ftp/detect-bruteforcing.bro .. code-block:: bro
:lines: 28-50 :caption: detect-bruteforcing.bro
event bro_init()
{
local r1: SumStats::Reducer = [$stream="ftp.failed_auth", $apply=set(SumStats::UNIQUE), $unique_max=double_to_count(bruteforce_threshold+2)];
SumStats::create([$name="ftp-detect-bruteforcing",
$epoch=bruteforce_measurement_interval,
$reducers=set(r1),
$threshold_val(key: SumStats::Key, result: SumStats::Result) =
{
return result["ftp.failed_auth"]$num+0.0;
},
$threshold=bruteforce_threshold,
$threshold_crossed(key: SumStats::Key, result: SumStats::Result) =
{
local r = result["ftp.failed_auth"];
local dur = duration_to_mins_secs(r$end-r$begin);
local plural = r$unique>1 ? "s" : "";
local message = fmt("%s had %d failed logins on %d FTP server%s in %s", key$host, r$num, r$unique, plural, dur);
NOTICE([$note=FTP::Bruteforcing,
$src=key$host,
$msg=message,
$identifier=cat(key$host)]);
}]);
}
Below is the final code for our script. Below is the final code for our script.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ftp/detect-bruteforcing.bro .. code-block:: bro
:caption: detect-bruteforcing.bro
.. btest:: ftp-bruteforce ##! FTP brute-forcing detector, triggering when too many rejected usernames or
##! failed passwords have occurred from a single address.
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/ftp/bruteforce.pcap protocols/ftp/detect-bruteforcing.bro @load base/protocols/ftp
@TEST-EXEC: btest-rst-include notice.log @load base/frameworks/sumstats
@load base/utils/time
module FTP;
export {
redef enum Notice::Type += {
## Indicates a host bruteforcing FTP logins by watching for too
## many rejected usernames or failed passwords.
Bruteforcing
};
## How many rejected usernames or passwords are required before being
## considered to be bruteforcing.
const bruteforce_threshold: double = 20 &redef;
## The time period in which the threshold needs to be crossed before
## being reset.
const bruteforce_measurement_interval = 15mins &redef;
}
event bro_init()
{
local r1: SumStats::Reducer = [$stream="ftp.failed_auth", $apply=set(SumStats::UNIQUE), $unique_max=double_to_count(bruteforce_threshold+2)];
SumStats::create([$name="ftp-detect-bruteforcing",
$epoch=bruteforce_measurement_interval,
$reducers=set(r1),
$threshold_val(key: SumStats::Key, result: SumStats::Result) =
{
return result["ftp.failed_auth"]$num+0.0;
},
$threshold=bruteforce_threshold,
$threshold_crossed(key: SumStats::Key, result: SumStats::Result) =
{
local r = result["ftp.failed_auth"];
local dur = duration_to_mins_secs(r$end-r$begin);
local plural = r$unique>1 ? "s" : "";
local message = fmt("%s had %d failed logins on %d FTP server%s in %s", key$host, r$num, r$unique, plural, dur);
NOTICE([$note=FTP::Bruteforcing,
$src=key$host,
$msg=message,
$identifier=cat(key$host)]);
}]);
}
event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool)
{
local cmd = c$ftp$cmdarg$cmd;
if ( cmd == "USER" || cmd == "PASS" )
{
if ( FTP::parse_ftp_reply_code(code)$x == 5 )
SumStats::observe("ftp.failed_auth", [$host=c$id$orig_h], [$str=cat(c$id$resp_h)]);
}
}
.. code-block:: console
$ bro -r ftp/bruteforce.pcap protocols/ftp/detect-bruteforcing.bro
$ cat notice.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2018-12-13-22-56-21
#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
1389721084.522861 - - - - - - - - - FTP::Bruteforcing 192.168.56.1 had 20 failed logins on 1 FTP server in 0m37s - 192.168.56.1 - - - - Notice::ACTION_LOG 3600.000000 F - - - - -
#close 2018-12-13-22-56-21
As a final note, the :doc:`detect-bruteforcing.bro As a final note, the :doc:`detect-bruteforcing.bro
</scripts/policy/protocols/ftp/detect-bruteforcing.bro>` script above is </scripts/policy/protocols/ftp/detect-bruteforcing.bro>` script above is

View file

@ -19,20 +19,6 @@ extensions = []
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('sphinx_input/ext')) sys.path.insert(0, os.path.abspath('sphinx_input/ext'))
# ----- Begin of BTest configuration. -----
btest = os.path.abspath("@CMAKE_SOURCE_DIR@/aux/btest")
brocut = os.path.abspath("@CMAKE_SOURCE_DIR@/build/aux/bro-aux/bro-cut")
bro = os.path.abspath("@CMAKE_SOURCE_DIR@/build/src")
os.environ["PATH"] += (":%s:%s/sphinx:%s:%s" % (btest, btest, bro, brocut))
sys.path.append(os.path.join(btest, "sphinx"))
extensions += ["btest-sphinx"]
btest_base="@CMAKE_SOURCE_DIR@/testing/btest"
btest_tests="doc/sphinx"
# ----- End of BTest configuration. -----
# ----- Begin of Broxygen configuration. ----- # ----- Begin of Broxygen configuration. -----
extensions += ["broxygen"] extensions += ["broxygen"]
bro_binary = os.path.abspath("@CMAKE_SOURCE_DIR@/build/src/bro") bro_binary = os.path.abspath("@CMAKE_SOURCE_DIR@/build/src/bro")
@ -49,9 +35,6 @@ os.environ["BROPATH"] = "@BROPATH@"
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc'] extensions += ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc']
os.environ["BRO_SRC_ROOT"] = "@CMAKE_SOURCE_DIR@"
os.environ["DOC_ROOT"] = "@CMAKE_SOURCE_DIR@/doc"
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx_input/_templates', 'sphinx_input/_static'] templates_path = ['sphinx_input/_templates', 'sphinx_input/_static']
@ -108,6 +91,8 @@ show_authors = True
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = 'sphinx'
highlight_language = 'none'
# A list of ignored prefixes for module index sorting. # A list of ignored prefixes for module index sorting.
#modindex_common_prefix = [] #modindex_common_prefix = []

View file

@ -296,11 +296,17 @@ Connecting to Peers
Bro can accept incoming connections by calling :bro:see:`Broker::listen`. Bro can accept incoming connections by calling :bro:see:`Broker::listen`.
.. btest-include:: ${DOC_ROOT}/frameworks/broker/connecting-listener.bro .. literalinclude:: broker/connecting-listener.bro
:caption: connecting-listener.bro
:language: bro
:linenos:
Bro can initiate outgoing connections by calling :bro:see:`Broker::peer`. Bro can initiate outgoing connections by calling :bro:see:`Broker::peer`.
.. btest-include:: ${DOC_ROOT}/frameworks/broker/connecting-connector.bro .. literalinclude:: broker/connecting-connector.bro
:caption: connecting-connector.bro
:language: bro
:linenos:
In either case, connection status updates are monitored via the In either case, connection status updates are monitored via the
:bro:see:`Broker::peer_added` and :bro:see:`Broker::peer_lost` events. :bro:see:`Broker::peer_added` and :bro:see:`Broker::peer_lost` events.
@ -317,7 +323,10 @@ more on how topics work and are chosen.
Use the :bro:see:`Broker::subscribe` function to subscribe to topics and Use the :bro:see:`Broker::subscribe` function to subscribe to topics and
define any event handlers for events that peers will send. define any event handlers for events that peers will send.
.. btest-include:: ${DOC_ROOT}/frameworks/broker/events-listener.bro .. literalinclude:: broker/events-listener.bro
:caption: events-listener.bro
:language: bro
:linenos:
There are two different ways to send events. There are two different ways to send events.
@ -333,7 +342,10 @@ whenever the event is called locally via the normal event invocation syntax.
When auto-publishing events, local event handlers for the event are called When auto-publishing events, local event handlers for the event are called
in addition to sending the event to any subscribed peers. in addition to sending the event to any subscribed peers.
.. btest-include:: ${DOC_ROOT}/frameworks/broker/events-connector.bro .. literalinclude:: broker/events-connector.bro
:caption: events-connector.bro
:language: bro
:linenos:
Note that the subscription model is prefix-based, meaning that if you subscribe Note that the subscription model is prefix-based, meaning that if you subscribe
to the "bro/events" topic prefix you would receive events that are published to the "bro/events" topic prefix you would receive events that are published
@ -342,16 +354,25 @@ to topic names "bro/events/foo" and "bro/events/bar" but not "bro/misc".
Remote Logging Remote Logging
-------------- --------------
.. btest-include:: ${DOC_ROOT}/frameworks/broker/testlog.bro .. literalinclude:: broker/testlog.bro
:caption: testlog.bro
:language: bro
:linenos:
To toggle remote logs, redef :bro:see:`Log::enable_remote_logging`. To toggle remote logs, redef :bro:see:`Log::enable_remote_logging`.
Use the :bro:see:`Broker::subscribe` function to advertise interest Use the :bro:see:`Broker::subscribe` function to advertise interest
in logs written by peers. The topic names that Bro uses are determined by in logs written by peers. The topic names that Bro uses are determined by
:bro:see:`Broker::log_topic`. :bro:see:`Broker::log_topic`.
.. btest-include:: ${DOC_ROOT}/frameworks/broker/logs-listener.bro .. literalinclude:: broker/logs-listener.bro
:caption: logs-listener.bro
:language: bro
:linenos:
.. btest-include:: ${DOC_ROOT}/frameworks/broker/logs-connector.bro .. literalinclude:: broker/logs-connector.bro
:caption: logs-connector.bro
:language: bro
:linenos:
Note that logging events are only raised locally on the node that performs Note that logging events are only raised locally on the node that performs
the :bro:see:`Log::write` and not automatically published to peers. the :bro:see:`Log::write` and not automatically published to peers.
@ -379,9 +400,15 @@ use. E.g. In-memory versus SQLite for persistence.
Data stores also support expiration on a per-key basis using an amount of Data stores also support expiration on a per-key basis using an amount of
time relative to the entry's last modification time. time relative to the entry's last modification time.
.. btest-include:: ${DOC_ROOT}/frameworks/broker/stores-listener.bro .. literalinclude:: broker/stores-listener.bro
:caption: stores-listener.bro
:language: bro
:linenos:
.. btest-include:: ${DOC_ROOT}/frameworks/broker/stores-connector.bro .. literalinclude:: broker/stores-connector.bro
:caption: stores-connector.bro
:language: bro
:linenos:
Note that all data store queries must be made within Bro's asynchronous Note that all data store queries must be made within Bro's asynchronous
``when`` statements and must specify a timeout block. ``when`` statements and must specify a timeout block.

View file

@ -36,11 +36,23 @@ bytes have been transferred so far, and its MIME type.
Here's a simple example: Here's a simple example:
.. btest-include:: ${DOC_ROOT}/frameworks/file_analysis_01.bro .. literalinclude:: file_analysis_01.bro
:caption:
:language: bro
:linenos:
.. btest:: file-analysis-01 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/get.trace ${DOC_ROOT}/frameworks/file_analysis_01.bro $ bro -r http/get.trace file_analysis_01.bro
file_state_remove
FakNcS1Jfe01uljb3
CHhAvVGS1DHFjwGM9
[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp]
HTTP
connection_state_remove
CHhAvVGS1DHFjwGM9
[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp]
HTTP
This doesn't perform any interesting analysis yet, but does highlight This doesn't perform any interesting analysis yet, but does highlight
the similarity between analysis of connections and files. Connections the similarity between analysis of connections and files. Connections
@ -71,11 +83,16 @@ explicit attachment decision.
Here's a simple example of how to use the MD5 file analyzer to Here's a simple example of how to use the MD5 file analyzer to
calculate the MD5 of plain text files: calculate the MD5 of plain text files:
.. btest-include:: ${DOC_ROOT}/frameworks/file_analysis_02.bro .. literalinclude:: file_analysis_02.bro
:caption:
:language: bro
:linenos:
.. btest:: file-analysis-02 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/get.trace ${DOC_ROOT}/frameworks/file_analysis_02.bro $ bro -r http/get.trace file_analysis_02.bro
new file, FakNcS1Jfe01uljb3
file_hash, FakNcS1Jfe01uljb3, md5, 397168fd09991a0e712254df7bc639ac
Some file analyzers might have tunable parameters that need to be Some file analyzers might have tunable parameters that need to be
specified in the call to :bro:see:`Files::add_analyzer`: specified in the call to :bro:see:`Files::add_analyzer`:
@ -109,19 +126,24 @@ in the same way it analyzes files that it sees coming over traffic from
a network interface it's monitoring. It only requires a call to a network interface it's monitoring. It only requires a call to
:bro:see:`Input::add_analysis`: :bro:see:`Input::add_analysis`:
.. btest-include:: ${DOC_ROOT}/frameworks/file_analysis_03.bro .. literalinclude:: file_analysis_03.bro
:caption:
:language: bro
:linenos:
Note that the "source" field of :bro:see:`fa_file` corresponds to the Note that the "source" field of :bro:see:`fa_file` corresponds to the
"name" field of :bro:see:`Input::AnalysisDescription` since that is what "name" field of :bro:see:`Input::AnalysisDescription` since that is what
the input framework uses to uniquely identify an input stream. the input framework uses to uniquely identify an input stream.
The output of the above script may be (assuming a file called "myfile" Example output of the above script may be:
exists):
.. btest:: file-analysis-03 .. code-block:: console
@TEST-EXEC: echo "Hello world" > myfile $ echo "Hello world" > myfile
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/frameworks/file_analysis_03.bro $ bro file_analysis_03.bro
new file, FZedLu4Ajcvge02jA8
file_hash, FZedLu4Ajcvge02jA8, md5, f0ef7081e1539ac00ef5b761b4fb01b3
file_state_remove
Nothing that special, but it at least verifies the MD5 file analyzer Nothing that special, but it at least verifies the MD5 file analyzer
saw all the bytes of the input file and calculated the checksum saw all the bytes of the input file and calculated the checksum

View file

@ -38,12 +38,10 @@ You have to define a filter which specifies SQLite as the writer.
The following example code adds SQLite as a filter for the connection log: The following example code adds SQLite as a filter for the connection log:
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-conn-filter.bro .. literalinclude:: sqlite-conn-filter.bro
:caption:
.. btest:: sqlite-conn-filter-check :language: bro
:linenos:
# Make sure this parses correctly at least.
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-conn-filter.bro
Bro will create the database file ``/var/db/conn.sqlite``, if it does not Bro will create the database file ``/var/db/conn.sqlite``, if it does not
already exist. It will also create a table with the name ``conn`` (if it already exist. It will also create a table with the name ``conn`` (if it
@ -115,12 +113,10 @@ The SQLite commands to create the schema are as follows::
After creating a file called ``hosts.sqlite`` with this content, we can After creating a file called ``hosts.sqlite`` with this content, we can
read the resulting table into Bro: read the resulting table into Bro:
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-read-table.bro .. literalinclude:: sqlite-read-table.bro
:caption:
.. btest:: sqlite-read-table-check :language: bro
:linenos:
# Make sure this parses correctly at least.
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-read-table.bro
Afterwards, that table can be used to check logins into hosts against Afterwards, that table can be used to check logins into hosts against
the available userlist. the available userlist.
@ -164,12 +160,10 @@ of files that are transmitted over the network. For each hash, a SQL-query
is run against SQLite. If the query returns with a result, we had a hit is run against SQLite. If the query returns with a result, we had a hit
against our malware-database and output the matching hash. against our malware-database and output the matching hash.
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-read-events.bro .. literalinclude:: sqlite-read-events.bro
:caption:
.. btest:: sqlite-read-events-check :language: bro
:linenos:
# Make sure this parses correctly at least.
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-read-events.bro
If you run this script against the trace in If you run this script against the trace in
``testing/btest/Traces/ftp/ipv4.trace``, you will get one hit. ``testing/btest/Traces/ftp/ipv4.trace``, you will get one hit.

View file

@ -133,17 +133,37 @@ start sending the rules to the added backend(s). To give a very simple example,
the following script will simply block the traffic of all connections that it the following script will simply block the traffic of all connections that it
sees being established: sees being established:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-1-drop-with-debug.bro .. literalinclude:: netcontrol-1-drop-with-debug.bro
:caption:
:language: bro
:linenos:
Running this script on a file containing one connection will cause the debug Running this script on a file containing one connection will cause the debug
plugin to print one line to the standard output, which contains information plugin to print one line to the standard output, which contains information
about the rule that was added. It will also cause creation of `netcontrol.log`, about the rule that was added. It will also cause creation of `netcontrol.log`,
which contains information about all actions that are taken by NetControl: which contains information about all actions that are taken by NetControl:
.. btest:: netcontrol-1-drop-with-debug.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-1-drop-with-debug.bro $ bro -C -r tls/ecdhe.pcap netcontrol-1-drop-with-debug.bro
@TEST-EXEC: btest-rst-cmd cat netcontrol.log netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::CONNECTION, conn=[orig_h=192.168.18.50, orig_p=56981/tcp, resp_h=74.125.239.97, resp_p=443/tcp], flow=<uninitialized>, ip=<uninitialized>, mac=<uninitialized>], expire=20.0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
$ cat netcontrol.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol
#open 2018-12-14-18-50-53
#fields ts rule_id category cmd state action target entity_type entity mod msg priority expire location plugin
#types time string enum string enum string enum string string string string int interval string string
0.000000 - NetControl::MESSAGE - - - - - - - activating plugin with priority 0 - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - activation finished - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - plugin initialization done - - - -
1398529018.678276 2 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::CONNECTION 192.168.18.50/56981<->74.125.239.97/443 - - 0 20.000000 - Debug-All
1398529018.678276 2 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::CONNECTION 192.168.18.50/56981<->74.125.239.97/443 - - 0 20.000000 - Debug-All
#close 2018-12-14-18-50-53
In our case, `netcontrol.log` contains several :bro:see:`NetControl::MESSAGE` In our case, `netcontrol.log` contains several :bro:see:`NetControl::MESSAGE`
entries, which show that the debug plugin has been initialized and added. entries, which show that the debug plugin has been initialized and added.
@ -159,39 +179,99 @@ additional log called `netcontrol_drop.log`. This log file is much more succinct
only contains information that is specific to drops that are enacted by only contains information that is specific to drops that are enacted by
NetControl: NetControl:
.. btest:: netcontrol-1-drop-with-debug.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd cat netcontrol_drop.log $ cat netcontrol_drop.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol_drop
#open 2018-12-14-18-50-53
#fields ts rule_id orig_h orig_p resp_h resp_p expire location
#types time string addr port addr port interval string
1398529018.678276 2 192.168.18.50 56981 74.125.239.97 443 20.000000 -
#close 2018-12-14-18-50-53
While this example of blocking all connections is usually not very useful, the While this example of blocking all connections is usually not very useful, the
high-level API gives an easy way to take action, for example when a host is high-level API gives an easy way to take action, for example when a host is
identified doing some harmful activity. To give a more realistic example, the identified doing some harmful activity. To give a more realistic example, the
following code automatically blocks a recognized SSH guesser: following code automatically blocks a recognized SSH guesser:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-2-ssh-guesser.bro .. literalinclude:: netcontrol-2-ssh-guesser.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-2-ssh-guesser.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/netcontrol-2-ssh-guesser.bro $ bro -C -r ssh/sshguess.pcap netcontrol-2-ssh-guesser.bro
@TEST-EXEC: btest-rst-cmd cat netcontrol.log netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.56.1/32, mac=<uninitialized>], expire=1.0 hr, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
$ cat netcontrol.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol
#open 2018-12-14-18-50-54
#fields ts rule_id category cmd state action target entity_type entity mod msg priority expire location plugin
#types time string enum string enum string enum string string string string int interval string string
0.000000 - NetControl::MESSAGE - - - - - - - activating plugin with priority 0 - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - activation finished - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - plugin initialization done - - - -
1427726759.303199 2 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.56.1/32 - - 0 3600.000000 - Debug-All
1427726759.303199 2 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.56.1/32 - - 0 3600.000000 - Debug-All
#close 2018-12-14-18-50-54
Note that in this case, instead of calling NetControl directly, we also can use Note that in this case, instead of calling NetControl directly, we also can use
the :bro:see:`Notice::ACTION_DROP` action of the notice framework: the :bro:see:`Notice::ACTION_DROP` action of the notice framework:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-3-ssh-guesser.bro .. literalinclude:: netcontrol-3-ssh-guesser.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-3-ssh-guesser.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/netcontrol-3-ssh-guesser.bro $ bro -C -r ssh/sshguess.pcap netcontrol-3-ssh-guesser.bro
@TEST-EXEC: btest-rst-cmd cat netcontrol.log netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.56.1/32, mac=<uninitialized>], expire=10.0 mins, priority=0, location=ACTION_DROP: T, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
$ cat netcontrol.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol
#open 2018-12-14-18-50-55
#fields ts rule_id category cmd state action target entity_type entity mod msg priority expire location plugin
#types time string enum string enum string enum string string string string int interval string string
0.000000 - NetControl::MESSAGE - - - - - - - activating plugin with priority 0 - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - activation finished - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - plugin initialization done - - - -
1427726759.303199 2 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.56.1/32 - - 0 600.000000 ACTION_DROP: T Debug-All
1427726759.303199 2 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.56.1/32 - - 0 600.000000 ACTION_DROP: T Debug-All
#close 2018-12-14-18-50-55
Using the :bro:see:`Notice::ACTION_DROP` action of the notice framework also Using the :bro:see:`Notice::ACTION_DROP` action of the notice framework also
will cause the `dropped` column in `notice.log` to be set to true each time that will cause the `dropped` column in `notice.log` to be set to true each time that
the NetControl framework enacts a block: the NetControl framework enacts a block:
.. btest:: netcontrol-3-ssh-guesser.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd cat notice.log $ cat notice.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2018-12-14-18-50-55
#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
1427726759.303199 - - - - - - - - - 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 - - - - Notice::ACTION_DROP,Notice::ACTION_LOG 3600.000000 F - - - - -
#close 2018-12-14-18-50-55
Rule API Rule API
-------- --------
@ -241,12 +321,32 @@ that the NetControl function has additional functionality, e.g. for logging.
Once again, we are going to test our function with a simple example that simply Once again, we are going to test our function with a simple example that simply
drops all connections on the network: drops all connections on the network:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-4-drop.bro .. literalinclude:: netcontrol-4-drop.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-4-drop.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-4-drop.bro $ bro -C -r tls/ecdhe.pcap netcontrol-4-drop.bro
@TEST-EXEC: btest-rst-cmd cat netcontrol.log netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::CONNECTION, conn=[orig_h=192.168.18.50, orig_p=56981/tcp, resp_h=74.125.239.97, resp_p=443/tcp], flow=<uninitialized>, ip=<uninitialized>, mac=<uninitialized>], expire=20.0 secs, priority=0, location=<uninitialized>, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
$ cat netcontrol.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol
#open 2018-12-14-18-50-55
#fields ts rule_id category cmd state action target entity_type entity mod msg priority expire location plugin
#types time string enum string enum string enum string string string string int interval string string
0.000000 - NetControl::MESSAGE - - - - - - - activating plugin with priority 0 - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - activation finished - - - Debug-All
0.000000 - NetControl::MESSAGE - - - - - - - plugin initialization done - - - -
1398529018.678276 2 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::CONNECTION 192.168.18.50/56981<->74.125.239.97/443 - - 0 20.000000 - Debug-All
1398529018.678276 2 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::CONNECTION 192.168.18.50/56981<->74.125.239.97/443 - - 0 20.000000 - Debug-All
#close 2018-12-14-18-50-55
The last example shows that :bro:see:`NetControl::add_rule` returns a string The last example shows that :bro:see:`NetControl::add_rule` returns a string
identifier that is unique for each rule (uniqueness is not preserved across identifier that is unique for each rule (uniqueness is not preserved across
@ -281,11 +381,16 @@ discarded before further processing.
Here is a simple example which tells Bro to discard all rules for connections Here is a simple example which tells Bro to discard all rules for connections
originating from the 192.168.* network: originating from the 192.168.* network:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-5-hook.bro .. literalinclude:: netcontrol-5-hook.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-5-hook.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-5-hook.bro $ bro -C -r tls/ecdhe.pcap netcontrol-5-hook.bro
netcontrol debug (Debug-All): init
Ignored connection from, 192.168.18.50
NetControl Events NetControl Events
***************** *****************
@ -355,11 +460,18 @@ Here is a simple example, which uses a trace that contains two connections from
the same IP address. After the first connection, the script recognizes that the the same IP address. After the first connection, the script recognizes that the
address is already blocked in the second connection. address is already blocked in the second connection.
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-6-find.bro .. literalinclude:: netcontrol-6-find.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-6-find.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/google-duplicate.trace ${DOC_ROOT}/frameworks/netcontrol-6-find.bro $ bro -C -r tls/google-duplicate.trace netcontrol-6-find.bro
netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::CONNECTION, conn=[orig_h=192.168.4.149, orig_p=60623/tcp, resp_h=74.125.239.129, resp_p=443/tcp], flow=<uninitialized>, ip=<uninitialized>, mac=<uninitialized>], expire=20.0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
Rule added
Rule already exists
Notice that the functions return vectors because it is possible that several Notice that the functions return vectors because it is possible that several
rules exist simultaneously that affect one IP; either there could be rules exist simultaneously that affect one IP; either there could be
@ -402,11 +514,16 @@ release is contained in the file
Using catch and release in your scripts is easy; just use Using catch and release in your scripts is easy; just use
:bro:see:`NetControl::drop_address_catch_release` like in this example: :bro:see:`NetControl::drop_address_catch_release` like in this example:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-7-catch-release.bro .. literalinclude:: netcontrol-7-catch-release.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-7-catch-release.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-7-catch-release.bro $ bro -C -r tls/ecdhe.pcap netcontrol-7-catch-release.bro
netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.18.50/32, mac=<uninitialized>], expire=10.0 mins, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
Note that you do not have to provide the block time for catch and release; Note that you do not have to provide the block time for catch and release;
instead, catch and release uses the time intervals specified in instead, catch and release uses the time intervals specified in
@ -418,9 +535,20 @@ first 10 minutes, it is blocked for 1 hour and then monitored for 24 hours, etc.
Catch and release adds its own new logfile in addition to the already existing Catch and release adds its own new logfile in addition to the already existing
ones (netcontrol_catch_release.log): ones (netcontrol_catch_release.log):
.. btest:: netcontrol-7-catch-release.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd cat netcontrol_catch_release.log $ cat netcontrol_catch_release.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol_catch_release
#open 2018-12-14-18-50-58
#fields ts rule_id ip action block_interval watch_interval blocked_until watched_until num_blocked location message
#types time string addr enum interval interval time time count string string
1398529018.678276 2 192.168.18.50 NetControl::DROP 600.000000 3600.000000 1398529618.678276 1398532618.678276 1 - -
1398529018.678276 2 192.168.18.50 NetControl::DROPPED 600.000000 3600.000000 1398529618.678276 1398532618.678276 1 - -
#close 2018-12-14-18-50-58
In addition to the blocking function, catch and release comes with the In addition to the blocking function, catch and release comes with the
:bro:see:`NetControl::get_catch_release_info` function to :bro:see:`NetControl::get_catch_release_info` function to
@ -531,27 +659,65 @@ the 192.168.17.0/24 network; all other rules will be passed on to the debug
plugin. We manually block a few addresses in the plugin. We manually block a few addresses in the
:bro:see:`NetControl::init_done` event to verify the correct functionality. :bro:see:`NetControl::init_done` event to verify the correct functionality.
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-8-multiple.bro .. literalinclude:: netcontrol-8-multiple.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-8-multiple.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/frameworks/netcontrol-8-multiple.bro $ bro netcontrol-8-multiple.bro
netcontrol debug (Debug-All): init
netcontrol debug (Debug-All): add_rule: [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::ADDRESS, conn=<uninitialized>, flow=<uninitialized>, ip=192.168.17.2/32, mac=<uninitialized>], expire=1.0 min, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=3, cid=3, _plugin_ids={\x0a\x0a}, _active_plugin_ids={\x0a\x0a}, _no_expire_plugins={\x0a\x0a}, _added=F]
As you can see, only the single block affecting the 192.168.17.0/24 network is As you can see, only the single block affecting the 192.168.17.0/24 network is
output to the command line. The other two lines are handled by the OpenFlow output to the command line. The other two lines are handled by the OpenFlow
plugin. We can verify this by looking at netcontrol.log. The plugin column shows plugin. We can verify this by looking at netcontrol.log. The plugin column shows
which plugin handled a rule and reveals that two rules were handled by OpenFlow: which plugin handled a rule and reveals that two rules were handled by OpenFlow:
.. btest:: netcontrol-8-multiple.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd cat netcontrol.log $ cat netcontrol.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path netcontrol
#open 2018-12-14-18-50-58
#fields ts rule_id category cmd state action target entity_type entity mod msg priority expire location plugin
#types time string enum string enum string enum string string string string int interval string string
1544813458.913148 - NetControl::MESSAGE - - - - - - - activating plugin with priority 0 - - - Debug-All
1544813458.913148 - NetControl::MESSAGE - - - - - - - activation finished - - - Debug-All
1544813458.913148 - NetControl::MESSAGE - - - - - - - activating plugin with priority 10 - - - Openflow-Log-42
1544813458.913148 - NetControl::MESSAGE - - - - - - - activation finished - - - Openflow-Log-42
1544813458.913148 - NetControl::MESSAGE - - - - - - - plugin initialization done - - - -
1544813458.913148 2 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 10.0.0.1/32 - - 0 60.000000 - Openflow-Log-42
1544813458.913148 3 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.17.2/32 - - 0 60.000000 - Debug-All
1544813458.913148 4 NetControl::RULE ADD NetControl::REQUESTED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.18.2/32 - - 0 60.000000 - Openflow-Log-42
1544813458.913148 3 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.17.2/32 - - 0 60.000000 - Debug-All
1544813458.913148 2 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 10.0.0.1/32 - - 0 60.000000 - Openflow-Log-42
1544813458.913148 4 NetControl::RULE ADD NetControl::SUCCEEDED NetControl::DROP NetControl::FORWARD NetControl::ADDRESS 192.168.18.2/32 - - 0 60.000000 - Openflow-Log-42
#close 2018-12-14-18-50-58
Furthermore, openflow.log also shows the two added rules, converted to OpenFlow Furthermore, openflow.log also shows the two added rules, converted to OpenFlow
flow mods: flow mods:
.. btest:: netcontrol-8-multiple.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd cat openflow.log $ cat openflow.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path openflow
#open 2018-12-14-18-50-58
#fields ts dpid match.in_port match.dl_src match.dl_dst match.dl_vlan match.dl_vlan_pcp match.dl_type match.nw_tos match.nw_proto match.nw_src match.nw_dst match.tp_src match.tp_dst flow_mod.cookie flow_mod.table_id flow_mod.command flow_mod.idle_timeout flow_mod.hard_timeout flow_mod.priority flow_mod.out_port flow_mod.out_group flow_mod.flags flow_mod.actions.out_ports flow_mod.actions.vlan_vid flow_mod.actions.vlan_pcp flow_mod.actions.vlan_strip flow_mod.actions.dl_src flow_mod.actions.dl_dst flow_mod.actions.nw_tos flow_mod.actions.nw_src flow_mod.actions.nw_dst flow_mod.actions.tp_src flow_mod.actions.tp_dst
#types time count count string string count count count count count subnet subnet count count count count enum count count count count count count vector[count] count count bool string string count addr addr count count
1544813458.913148 42 - - - - - 2048 - - 10.0.0.1/32 - - - 4398046511108 - OpenFlow::OFPFC_ADD 0 60 0 - - 1 (empty) - - F - - - - - - -
1544813458.913148 42 - - - - - 2048 - - - 10.0.0.1/32 - - 4398046511109 - OpenFlow::OFPFC_ADD 0 60 0 - - 1 (empty) - - F - - - - - - -
1544813458.913148 42 - - - - - 2048 - - 192.168.18.2/32 - - - 4398046511112 - OpenFlow::OFPFC_ADD 0 60 0 - - 1 (empty) - - F - - - - - - -
1544813458.913148 42 - - - - - 2048 - - - 192.168.18.2/32 - - 4398046511113 - OpenFlow::OFPFC_ADD 0 60 0 - - 1 (empty) - - F - - - - - - -
#close 2018-12-14-18-50-58
.. note:: .. note::
@ -613,16 +779,29 @@ raise the :bro:see:`NetControl::rule_added` and
:bro:see:`NetControl::rule_removed` events in your plugin to let NetControl know :bro:see:`NetControl::rule_removed` events in your plugin to let NetControl know
when a rule was added and removed successfully. when a rule was added and removed successfully.
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-9-skeleton.bro .. literalinclude:: netcontrol-9-skeleton.bro
:caption:
:language: bro
:linenos:
This example is already fully functional and we can use it with a script similar This example is already fully functional and we can use it with a script similar
to our very first example: to our very first example:
.. btest-include:: ${DOC_ROOT}/frameworks/netcontrol-10-use-skeleton.bro .. literalinclude:: netcontrol-10-use-skeleton.bro
:caption:
:language: bro
:linenos:
.. btest:: netcontrol-9-skeleton.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/tls/ecdhe.pcap ${DOC_ROOT}/frameworks/netcontrol-9-skeleton.bro ${DOC_ROOT}/frameworks/netcontrol-10-use-skeleton.bro $ bro -C -r tls/ecdhe.pcap netcontrol-10-use-skeleton.bro
add, [ty=NetControl::DROP, target=NetControl::FORWARD, entity=[ty=NetControl::CONNECTION, conn=[orig_h=192.168.18.50, orig_p=56981/tcp, resp_h=74.125.239.97, resp_p=443/tcp], flow=<uninitialized>, ip=<uninitialized>, mac=<uninitialized>], expire=20.0 secs, priority=0, location=, out_port=<uninitialized>, mod=<uninitialized>, id=2, cid=2, _plugin_ids={
}, _active_plugin_ids={
}, _no_expire_plugins={
}, _added=F]
If you want to write your own plugins, it will be worthwhile to look at the If you want to write your own plugins, it will be worthwhile to look at the
plugins that ship with the NetControl framework to see how they define the plugins that ship with the NetControl framework to see how they define the

View file

@ -91,12 +91,25 @@ Here's a simple example which tells Bro to send an email for all notices of
type :bro:see:`SSH::Password_Guessing` if the guesser attempted to log in to type :bro:see:`SSH::Password_Guessing` if the guesser attempted to log in to
the server at 192.168.56.103: the server at 192.168.56.103:
.. btest-include:: ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro .. literalinclude:: notice_ssh_guesser.bro
:caption:
:language: bro
:linenos:
.. btest:: notice_ssh_guesser.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro $ bro -C -r ssh/sshguess.pcap notice_ssh_guesser.bro
@TEST-EXEC: btest-rst-cmd cat notice.log $ cat notice.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2018-12-13-22-56-35
#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
1427726759.303199 - - - - - - - - - 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 - - - - Notice::ACTION_EMAIL,Notice::ACTION_LOG 3600.000000 F - - - - -
#close 2018-12-13-22-56-35
.. note:: .. note::

View file

@ -73,15 +73,18 @@ Sumstats provides a simple way of approaching the problem of trying to count
the number of connections over a given time interval. Here is a script with the number of connections over a given time interval. Here is a script with
inline documentation that does this with the Sumstats framework: inline documentation that does this with the Sumstats framework:
.. btest-include:: ${DOC_ROOT}/frameworks/sumstats-countconns.bro .. literalinclude:: sumstats-countconns.bro
:caption:
:language: bro
:linenos:
When run on a sample PCAP file from the Bro test suite, the following output When run on a sample PCAP file from the Bro test suite, the following output
is created: is created:
.. btest:: sumstats-countconns .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/workshop_2011_browse.trace ${DOC_ROOT}/frameworks/sumstats-countconns.bro
$ bro -r workshop_2011_browse.trace sumstats-countconns.bro
Number of connections established: 6
Toy scan detection Toy scan detection
------------------ ------------------
@ -92,14 +95,18 @@ demonstrate how thresholding works in Sumstats and is not meant to be a
real-world functional example, that is left to the real-world functional example, that is left to the
:doc:`/scripts/policy/misc/scan.bro` script that is included with Bro. :doc:`/scripts/policy/misc/scan.bro` script that is included with Bro.
.. btest-include:: ${DOC_ROOT}/frameworks/sumstats-toy-scan.bro .. literalinclude:: sumstats-toy-scan.bro
:caption:
:language: bro
:linenos:
Let's see if there are any hosts that crossed the threshold in a PCAP file Let's see if there are any hosts that crossed the threshold in a PCAP file
containing a host running nmap: containing a host running nmap:
.. btest:: sumstats-toy-scan .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/nmap-vsn.trace ${DOC_ROOT}/frameworks/sumstats-toy-scan.bro $ bro -r nmap-vsn.trace sumstats-toy-scan.bro
192.168.1.71 attempted 5 or more connections
It seems the host running nmap was detected! It seems the host running nmap was detected!

View file

@ -84,31 +84,43 @@ use this to identify a proxy server.
We can write a basic script in Bro to handle the http_reply event and We can write a basic script in Bro to handle the http_reply event and
detect a reply for a ``GET http://`` request. detect a reply for a ``GET http://`` request.
.. btest-include:: ${DOC_ROOT}/httpmonitor/http_proxy_01.bro .. literalinclude:: http_proxy_01.bro
:caption:
:language: bro
:linenos:
.. btest:: http_proxy_01 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/proxy.pcap ${DOC_ROOT}/httpmonitor/http_proxy_01.bro $ bro -r http/proxy.pcap http_proxy_01.bro
A local server is acting as an open proxy: 192.168.56.101
Basically, the script is checking for a "200 OK" status code on a reply Basically, the script is checking for a "200 OK" status code on a reply
for a request that includes "http:" (case insensitive). In reality, the for a request that includes "http:" (case insensitive). In reality, the
HTTP protocol defines several success status codes other than 200, so we HTTP protocol defines several success status codes other than 200, so we
will extend our basic script to also consider the additional codes. will extend our basic script to also consider the additional codes.
.. btest-include:: ${DOC_ROOT}/httpmonitor/http_proxy_02.bro .. literalinclude:: http_proxy_02.bro
:caption:
:language: bro
:linenos:
.. btest:: http_proxy_02 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/proxy.pcap ${DOC_ROOT}/httpmonitor/http_proxy_02.bro $ bro -r http/proxy.pcap http_proxy_02.bro
A local server is acting as an open proxy: 192.168.56.101
Next, we will make sure that the responding proxy is part of our local Next, we will make sure that the responding proxy is part of our local
network. network.
.. btest-include:: ${DOC_ROOT}/httpmonitor/http_proxy_03.bro .. literalinclude:: http_proxy_03.bro
:caption:
:language: bro
:linenos:
.. btest:: http_proxy_03 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/proxy.pcap ${DOC_ROOT}/httpmonitor/http_proxy_03.bro $ bro -r http/proxy.pcap http_proxy_03.bro
A local server is acting as an open proxy: 192.168.56.101
.. note:: .. note::
@ -123,12 +135,25 @@ we will tag the traffic accordingly and define a new ``Open_Proxy``
notification has been fired, we will further suppress it for one day. notification has been fired, we will further suppress it for one day.
Below is the complete script. Below is the complete script.
.. btest-include:: ${DOC_ROOT}/httpmonitor/http_proxy_04.bro .. literalinclude:: http_proxy_04.bro
:caption:
:language: bro
:linenos:
.. btest:: http_proxy_04 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/proxy.pcap ${DOC_ROOT}/httpmonitor/http_proxy_04.bro $ bro -r http/proxy.pcap http_proxy_04.bro
@TEST-EXEC: btest-rst-include notice.log $ cat notice.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2018-12-13-22-56-39
#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
1389654450.449603 CHhAvVGS1DHFjwGM9 192.168.56.1 52679 192.168.56.101 80 - - - tcp HTTP::Open_Proxy A local server is acting as an open proxy: 192.168.56.101 - 192.168.56.1 192.168.56.101 80 - - Notice::ACTION_LOG 86400.000000 F - - - - -
#close 2018-12-13-22-56-40
Note that this script only logs the presence of the proxy to Note that this script only logs the presence of the proxy to
``notice.log``, but if an additional email is desired (and email ``notice.log``, but if an additional email is desired (and email
@ -148,11 +173,20 @@ instruct Bro to create a copy of all files of certain types that it sees
using the :ref:`File Analysis Framework <file-analysis-framework>` using the :ref:`File Analysis Framework <file-analysis-framework>`
(introduced with Bro 2.2): (introduced with Bro 2.2):
.. btest-include:: ${DOC_ROOT}/httpmonitor/file_extraction.bro .. literalinclude:: file_extraction.bro
:caption:
:language: bro
:linenos:
.. btest:: file_extraction .. code-block:: console
@TEST-EXEC: btest-rst-cmd -n 5 bro -r ${TRACES}/http/bro.org.pcap ${DOC_ROOT}/httpmonitor/file_extraction.bro $ bro -r bro.org.pcap file_extraction.bro
Extracting file HTTP-FiIpIB2hRQSDBOSJRg.html
Extracting file HTTP-FMG4bMmVV64eOsCb.txt
Extracting file HTTP-FnaT2a3UDd093opCB9.txt
Extracting file HTTP-FfQGqj4Fhh3pH7nVQj.txt
Extracting file HTTP-FsvATF146kf1Emc21j.txt
[...]
Here, the ``mime_to_ext`` table serves two purposes. It defines which Here, the ``mime_to_ext`` table serves two purposes. It defines which
mime types to extract and also the file suffix of the extracted files. mime types to extract and also the file suffix of the extracted files.

View file

@ -39,13 +39,23 @@ to the appropriate log file.
As the fields of the log entries can be further customized by the As the fields of the log entries can be further customized by the
user, the Logging Framework makes use of a header block to ensure that user, the Logging Framework makes use of a header block to ensure that
it remains self-describing. This header entry can be see by running it remains self-describing. Here's the first few lines of a ``conn.log``.
the Unix utility ``head`` and outputting the first lines of the file:
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r $TRACES/wikipedia.trace $ cat conn.log
@TEST-EXEC: btest-rst-include -n 15 conn.log #separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path conn
#open 2018-12-10-22-18-00
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig local_resp missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents
#types time string addr port addr port enum string interval count count string bool bool count string count count count count set[string]
1300475167.096535 CHhAvVGS1DHFjwGM9 141.142.220.202 5353 224.0.0.251 5353 udp dns - - - S0 - - 0 D 1 73 0 0 -
1300475167.097012 ClEkJM2Vm5giqnMf4h fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 udp dns - - - S0 - - 0 D 1 199 0 0 -
1300475167.099816 C4J4Th3PJpwUYZZ6gc 141.142.220.50 5353 224.0.0.251 5353 udp dns - - - S0 - - 0 D 1 179 0 0 -
[...]
As you can see, the header consists of lines prefixed by ``#`` and As you can see, the header consists of lines prefixed by ``#`` and
includes information such as what separators are being used for includes information such as what separators are being used for
@ -129,15 +139,37 @@ require the user to refer to fields referenced by their position).
For example, the following command extracts just the given columns For example, the following command extracts just the given columns
from a ``conn.log``: from a ``conn.log``:
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd -n 10 "cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration" $ cat conn.log | bro-cut id.orig_h id.orig_p id.resp_h duration
141.142.220.202 5353 224.0.0.251 -
fe80::217:f2ff:fed7:cf65 5353 ff02::fb -
141.142.220.50 5353 224.0.0.251 -
141.142.220.118 43927 141.142.2.2 0.000435
141.142.220.118 37676 141.142.2.2 0.000420
141.142.220.118 40526 141.142.2.2 0.000392
141.142.220.118 32902 141.142.2.2 0.000317
141.142.220.118 59816 141.142.2.2 0.000343
141.142.220.118 59714 141.142.2.2 0.000375
141.142.220.118 58206 141.142.2.2 0.000339
[...]
The corresponding ``awk`` command will look like this: The corresponding ``awk`` command will look like this:
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd -n 10 awk \'/^[^#]/ {print \$3, \$4, \$5, \$6, \$9}\' conn.log $ awk '/^[^#]/ {print $3, $4, $5, $6, $9}' conn.log
141.142.220.202 5353 224.0.0.251 5353 -
fe80::217:f2ff:fed7:cf65 5353 ff02::fb 5353 -
141.142.220.50 5353 224.0.0.251 5353 -
141.142.220.118 43927 141.142.2.2 53 0.000435
141.142.220.118 37676 141.142.2.2 53 0.000420
141.142.220.118 40526 141.142.2.2 53 0.000392
141.142.220.118 32902 141.142.2.2 53 0.000317
141.142.220.118 59816 141.142.2.2 53 0.000343
141.142.220.118 59714 141.142.2.2 53 0.000375
141.142.220.118 58206 141.142.2.2 53 0.000339
[...]
While the output is similar, the advantages to using bro-cut over While the output is similar, the advantages to using bro-cut over
``awk`` lay in that, while ``awk`` is flexible and powerful, ``bro-cut`` ``awk`` lay in that, while ``awk`` is flexible and powerful, ``bro-cut``
@ -191,17 +223,29 @@ includes the human readable time stamp, the unique identifier, the
HTTP ``Host``, and HTTP ``URI`` as extracted from the ``http.log`` HTTP ``Host``, and HTTP ``URI`` as extracted from the ``http.log``
file: file:
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -d ts uid host uri < http.log" $ bro-cut -d ts uid host uri < http.log
2011-03-18T19:06:08+0000 CUM0KZ3MLUfNB0cl11 bits.wikimedia.org /skins-1.5/monobook/main.css
2011-03-18T19:06:08+0000 CwjjYJ2WqgTbAqiHl6 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png
2011-03-18T19:06:08+0000 C3eiCBGOLw3VtHfOj upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png
2011-03-18T19:06:08+0000 Ck51lg1bScffFj34Ri upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png
2011-03-18T19:06:08+0000 CtxTCR2Yer0FR1tIBg upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png
[...]
Often times log files from multiple sources are stored in UTC time to Often times log files from multiple sources are stored in UTC time to
allow easy correlation. Converting the timestamp from a log file to allow easy correlation. Converting the timestamp from a log file to
UTC can be accomplished with the ``-u`` option: UTC can be accomplished with the ``-u`` option:
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -u ts uid host uri < http.log" $ bro-cut -u ts uid host uri < http.log
2011-03-18T19:06:08+0000 CUM0KZ3MLUfNB0cl11 bits.wikimedia.org /skins-1.5/monobook/main.css
2011-03-18T19:06:08+0000 CwjjYJ2WqgTbAqiHl6 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png
2011-03-18T19:06:08+0000 C3eiCBGOLw3VtHfOj upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png
2011-03-18T19:06:08+0000 Ck51lg1bScffFj34Ri upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png
2011-03-18T19:06:08+0000 CtxTCR2Yer0FR1tIBg upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png
[...]
The default time format when using the ``-d`` or ``-u`` is the The default time format when using the ``-d`` or ``-u`` is the
``strftime`` format string ``%Y-%m-%dT%H:%M:%S%z`` which results in a ``strftime`` format string ``%Y-%m-%dT%H:%M:%S%z`` which results in a
@ -211,9 +255,15 @@ using the ``-D`` and ``-U`` flags, using the standard ``strftime``
syntax. For example, to format the timestamp in the US-typical "Middle syntax. For example, to format the timestamp in the US-typical "Middle
Endian" you could use a format string of: ``%d-%m-%YT%H:%M:%S%z`` Endian" you could use a format string of: ``%d-%m-%YT%H:%M:%S%z``
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd -n 5 "bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log" $ bro-cut -D %d-%m-%YT%H:%M:%S%z ts uid host uri < http.log
18-03-2011T19:06:08+0000 CUM0KZ3MLUfNB0cl11 bits.wikimedia.org /skins-1.5/monobook/main.css
18-03-2011T19:06:08+0000 CwjjYJ2WqgTbAqiHl6 upload.wikimedia.org /wikipedia/commons/6/63/Wikipedia-logo.png
18-03-2011T19:06:08+0000 C3eiCBGOLw3VtHfOj upload.wikimedia.org /wikipedia/commons/thumb/b/bb/Wikipedia_wordmark.svg/174px-Wikipedia_wordmark.svg.png
18-03-2011T19:06:08+0000 Ck51lg1bScffFj34Ri upload.wikimedia.org /wikipedia/commons/b/bd/Bookshelf-40x201_6.png
18-03-2011T19:06:08+0000 CtxTCR2Yer0FR1tIBg upload.wikimedia.org /wikipedia/commons/thumb/8/8a/Wikinews-logo.png/35px-Wikinews-logo.png
[...]
See ``man strfime`` for more options for the format string. See ``man strfime`` for more options for the format string.
@ -235,16 +285,22 @@ largest number of bytes from the responder by redirecting the output
for ``cat conn.log`` into bro-cut to extract the UID and the for ``cat conn.log`` into bro-cut to extract the UID and the
resp_bytes, then sorting that output by the resp_bytes field. resp_bytes, then sorting that output by the resp_bytes field.
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd "cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5" $ cat conn.log | bro-cut uid resp_bytes | sort -nrk2 | head -5
CwjjYJ2WqgTbAqiHl6 734
CtxTCR2Yer0FR1tIBg 734
Ck51lg1bScffFj34Ri 734
CLNN1k2QMum1aexUK7 734
CykQaM33ztNt0csB9a 733
Taking the UID of the first of the top responses, we can now Taking the UID of the first of the top responses, we can now
crossreference that with the UIDs in the ``http.log`` file. crossreference that with the UIDs in the ``http.log`` file.
.. btest:: using_bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd "cat http.log | bro-cut uid id.resp_h method status_code host uri | grep UM0KZ3MLUfNB0cl11" $ cat http.log | bro-cut uid id.resp_h method status_code host uri | grep UM0KZ3MLUfNB0cl11
CUM0KZ3MLUfNB0cl11 208.80.152.118 GET 304 bits.wikimedia.org /skins-1.5/monobook/main.css
As you can see there are two HTTP ``GET`` requests within the As you can see there are two HTTP ``GET`` requests within the
session that Bro identified and logged. Given that HTTP is a stream session that Bro identified and logged. Given that HTTP is a stream

View file

@ -37,32 +37,69 @@ in the MIME type, size of the file ("response_body_len"), and the
originator host ("orig_h"). We use the MIME type as our key and create originator host ("orig_h"). We use the MIME type as our key and create
observers for the other two values. observers for the other two values.
.. btest-include:: ${DOC_ROOT}/mimestats/mimestats.bro .. literalinclude:: mimestats.bro
:lines: 6-29, 54-64 :caption:
:language: bro
:linenos:
:lines: 6-29
:lineno-start: 6
.. literalinclude:: mimestats.bro
:caption:
:language: bro
:linenos:
:lines: 54-64
:lineno-start: 54
Next, we create the reducers. The first will accumulate file sizes Next, we create the reducers. The first will accumulate file sizes
and the second will make sure we only store a host ID once. Below is and the second will make sure we only store a host ID once. Below is
the partial code from a :bro:see:`bro_init` handler. the partial code from a :bro:see:`bro_init` handler.
.. btest-include:: ${DOC_ROOT}/mimestats/mimestats.bro .. literalinclude:: mimestats.bro
:lines: 34-37 :caption:
:language: bro
:linenos:
:lines: 34-37
:lineno-start: 34
In our final step, we create the SumStats where we check for the In our final step, we create the SumStats where we check for the
observation interval. Once it expires, we populate the record observation interval. Once it expires, we populate the record
(defined above) with all the relevant data and write it to a log. (defined above) with all the relevant data and write it to a log.
.. btest-include:: ${DOC_ROOT}/mimestats/mimestats.bro .. literalinclude:: mimestats.bro
:lines: 38-51 :caption:
:language: bro
:linenos:
:lines: 38-51
:lineno-start: 38
After putting the three pieces together we end up with the following final code for After putting the three pieces together we end up with the following
our script. final code for our script.
.. btest-include:: ${DOC_ROOT}/mimestats/mimestats.bro .. literalinclude:: mimestats.bro
:caption:
:language: bro
:linenos:
.. btest:: mimestats .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/http/bro.org.pcap ${DOC_ROOT}/mimestats/mimestats.bro $ bro -r http/bro.org.pcap mimestats.bro
@TEST-EXEC: btest-rst-include mime_metrics.log #separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path mime_metrics
#open 2018-12-14-16-25-06
#fields ts ts_delta mtype uniq_hosts hits bytes
#types time interval string count count count
1389719059.311698 300.000000 image/png 1 9 82176
1389719059.311698 300.000000 image/gif 1 1 172
1389719059.311698 300.000000 image/x-icon 1 2 2300
1389719059.311698 300.000000 text/html 1 2 42231
1389719059.311698 300.000000 text/plain 1 15 128001
1389719059.311698 300.000000 image/jpeg 1 1 186859
1389719059.311698 300.000000 application/pgp-signature 1 1 836
#close 2018-12-14-16-25-06
.. note:: .. note::

View file

@ -255,12 +255,25 @@ action taken on notices can be user-defined.
In ``local.bro``, let's define a new ``policy`` hook handler body: In ``local.bro``, let's define a new ``policy`` hook handler body:
.. btest-include:: ${DOC_ROOT}/quickstart/conditional-notice.bro .. literalinclude:: conditional-notice.bro
:caption:
:language: bro
:linenos:
.. btest:: conditional-notice .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/tls/tls-expired-cert.trace ${DOC_ROOT}/quickstart/conditional-notice.bro $ bro -r tls/tls-expired-cert.trace conditional-notice.bro
@TEST-EXEC: btest-rst-cmd cat notice.log $ cat notice.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2018-12-14-17-36-05
#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
1394745603.293028 CHhAvVGS1DHFjwGM9 192.168.4.149 60539 87.98.220.10 443 F1fX1R2cDOzbvg17ye - - tcp SSL::Certificate_Expired Certificate CN=www.spidh.org,OU=COMODO SSL,OU=Domain Control Validated expired at 2014-03-04-23:59:59.000000000 - 192.168.4.149 87.98.220.10 443 - - Notice::ACTION_EMAIL,Notice::ACTION_LOG 86400.000000 F - - - - -
#close 2018-12-14-17-36-05
You'll just have to trust the syntax for now, but what we've done is You'll just have to trust the syntax for now, but what we've done is
first declare our own variable to hold a set of watched addresses, first declare our own variable to hold a set of watched addresses,

View file

@ -37,10 +37,85 @@ Hash registry includes the ability to do a host lookup on a domain with the form
Team Cymru also populates the TXT record of their DNS responses with both a "first seen" Team Cymru also populates the TXT record of their DNS responses with both a "first seen"
timestamp and a numerical "detection rate". The important aspect to understand is Bro already timestamp and a numerical "detection rate". The important aspect to understand is Bro already
generating hashes for files via the Files framework, but it is the generating hashes for files via the Files framework, but it is the
script ``detect-MHR.bro`` that is responsible for generating the script :doc:`/scripts/policy/frameworks/files/detect-MHR.bro`
that is responsible for generating the
appropriate DNS lookup, parsing the response, and generating a notice if appropriate. appropriate DNS lookup, parsing the response, and generating a notice if appropriate.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro .. code-block:: bro
:caption: detect-MHR.bro
##! Detect file downloads that have hash values matching files in Team
##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/).
@load base/frameworks/files
@load base/frameworks/notice
@load frameworks/files/hash-all-files
module TeamCymruMalwareHashRegistry;
export {
redef enum Notice::Type += {
## The hash value of a file transferred over HTTP matched in the
## malware hash registry.
Match
};
## File types to attempt matching against the Malware Hash Registry.
option match_file_types = /application\/x-dosexec/ |
/application\/vnd.ms-cab-compressed/ |
/application\/pdf/ |
/application\/x-shockwave-flash/ |
/application\/x-java-applet/ |
/application\/jar/ |
/video\/mp4/;
## The Match notice has a sub message with a URL where you can get more
## information about the file. The %s will be replaced with the SHA-1
## hash of the file.
option match_sub_url = "https://www.virustotal.com/en/search/?query=%s";
## The malware hash registry runs each malware sample through several
## A/V engines. Team Cymru returns a percentage to indicate how
## many A/V engines flagged the sample as malicious. This threshold
## allows you to require a minimum detection rate.
option notice_threshold = 10;
}
function do_mhr_lookup(hash: string, fi: Notice::FileInfo)
{
local hash_domain = fmt("%s.malware.hash.cymru.com", hash);
when ( local MHR_result = lookup_hostname_txt(hash_domain) )
{
# Data is returned as "<dateFirstDetected> <detectionRate>"
local MHR_answer = split_string1(MHR_result, / /);
if ( |MHR_answer| == 2 )
{
local mhr_detect_rate = to_count(MHR_answer[1]);
if ( mhr_detect_rate >= notice_threshold )
{
local mhr_first_detected = double_to_time(to_double(MHR_answer[0]));
local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected);
local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected);
local virustotal_url = fmt(match_sub_url, hash);
# We don't have the full fa_file record here in order to
# avoid the "when" statement cloning it (expensive!).
local n: Notice::Info = Notice::Info($note=Match, $msg=message, $sub=virustotal_url);
Notice::populate_file_info2(fi, n);
NOTICE(n);
}
}
}
}
event file_hash(f: fa_file, kind: string, hash: string)
{
if ( kind == "sha1" && f?$info && f$info?$mime_type &&
match_file_types in f$info$mime_type )
do_mhr_lookup(hash, Notice::create_file_info(f));
}
Visually, there are three distinct sections of the script. First, there is a base Visually, there are three distinct sections of the script. First, there is a base
level with no indentation where libraries are included in the script through ``@load`` level with no indentation where libraries are included in the script through ``@load``
@ -51,8 +126,12 @@ specific event (``event file_hash``). Don't get discouraged if you don't
understand every section of the script; we'll cover the basics of the understand every section of the script; we'll cover the basics of the
script and much more in following sections. script and much more in following sections.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro .. code-block:: bro
:lines: 4-6 :caption: detect-MHR.bro
@load base/frameworks/files
@load base/frameworks/notice
@load frameworks/files/hash-all-files
The first part of the script consists of ``@load`` directives which The first part of the script consists of ``@load`` directives which
process the ``__load__.bro`` script in the process the ``__load__.bro`` script in the
@ -66,8 +145,36 @@ this level of granularity might not be entirely necessary. The ``@load`` direct
are ensuring the Files framework, the Notice framework and the script to hash all files has are ensuring the Files framework, the Notice framework and the script to hash all files has
been loaded by Bro. been loaded by Bro.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro .. code-block:: bro
:lines: 10-36 :caption: detect-MHR.bro
export {
redef enum Notice::Type += {
## The hash value of a file transferred over HTTP matched in the
## malware hash registry.
Match
};
## File types to attempt matching against the Malware Hash Registry.
option match_file_types = /application\/x-dosexec/ |
/application\/vnd.ms-cab-compressed/ |
/application\/pdf/ |
/application\/x-shockwave-flash/ |
/application\/x-java-applet/ |
/application\/jar/ |
/video\/mp4/;
## The Match notice has a sub message with a URL where you can get more
## information about the file. The %s will be replaced with the SHA-1
## hash of the file.
option match_sub_url = "https://www.virustotal.com/en/search/?query=%s";
## The malware hash registry runs each malware sample through several
## A/V engines. Team Cymru returns a percentage to indicate how
## many A/V engines flagged the sample as malicious. This threshold
## allows you to require a minimum detection rate.
option notice_threshold = 10;
}
The export section redefines an enumerable constant that describes the The export section redefines an enumerable constant that describes the
type of notice we will generate with the Notice framework. Bro type of notice we will generate with the Notice framework. Bro
@ -89,8 +196,43 @@ Up until this point, the script has merely done some basic setup. With
the next section, the script starts to define instructions to take in the next section, the script starts to define instructions to take in
a given event. a given event.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/frameworks/files/detect-MHR.bro .. code-block:: bro
:lines: 38-71 :caption: detect-MHR.bro
function do_mhr_lookup(hash: string, fi: Notice::FileInfo)
{
local hash_domain = fmt("%s.malware.hash.cymru.com", hash);
when ( local MHR_result = lookup_hostname_txt(hash_domain) )
{
# Data is returned as "<dateFirstDetected> <detectionRate>"
local MHR_answer = split_string1(MHR_result, / /);
if ( |MHR_answer| == 2 )
{
local mhr_detect_rate = to_count(MHR_answer[1]);
if ( mhr_detect_rate >= notice_threshold )
{
local mhr_first_detected = double_to_time(to_double(MHR_answer[0]));
local readable_first_detected = strftime("%Y-%m-%d %H:%M:%S", mhr_first_detected);
local message = fmt("Malware Hash Registry Detection rate: %d%% Last seen: %s", mhr_detect_rate, readable_first_detected);
local virustotal_url = fmt(match_sub_url, hash);
# We don't have the full fa_file record here in order to
# avoid the "when" statement cloning it (expensive!).
local n: Notice::Info = Notice::Info($note=Match, $msg=message, $sub=virustotal_url);
Notice::populate_file_info2(fi, n);
NOTICE(n);
}
}
}
}
event file_hash(f: fa_file, kind: string, hash: string)
{
if ( kind == "sha1" && f?$info && f$info?$mime_type &&
match_file_types in f$info$mime_type )
do_mhr_lookup(hash, Notice::create_file_info(f));
The workhorse of the script is contained in the event handler for The workhorse of the script is contained in the event handler for
``file_hash``. The :bro:see:`file_hash` event allows scripts to access ``file_hash``. The :bro:see:`file_hash` event allows scripts to access
@ -182,8 +324,34 @@ This effort resulted in built-in-function files organized such that
each entry contains a descriptive event name, the arguments passed to each entry contains a descriptive event name, the arguments passed to
the event, and a concise explanation of the functions use. the event, and a concise explanation of the functions use.
.. btest-include:: ${BRO_SRC_ROOT}/build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro .. code-block:: bro
:lines: 29-54
## Generated for DNS requests. For requests with multiple queries, this event
## is raised once for each.
##
## See `Wikipedia <http://en.wikipedia.org/wiki/Domain_Name_System>`__ for more
## information about the DNS protocol. Bro analyzes both UDP and TCP DNS
## sessions.
##
## c: The connection, which may be UDP or TCP depending on the type of the
## transport-layer session being analyzed.
##
## msg: The parsed DNS message header.
##
## query: The queried name.
##
## qtype: The queried resource record type.
##
## qclass: The queried resource record class.
##
## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%);
Above is a segment of the documentation for the event Above is a segment of the documentation for the event
:bro:id:`dns_request` (and the preceding link points to the :bro:id:`dns_request` (and the preceding link points to the
@ -226,7 +394,10 @@ remove this event from memory, effectively forgetting about it. Let's
take a look at a simple example script, that will output the connection record take a look at a simple example script, that will output the connection record
for a single connection. for a single connection.
.. btest-include:: ${DOC_ROOT}/scripting/connection_record_01.bro .. literalinclude:: connection_record_01.bro
:caption:
:language: bro
:linenos:
Again, we start with ``@load``, this time importing the Again, we start with ``@load``, this time importing the
:doc:`/scripts/base/protocols/conn/index` scripts which supply the tracking :doc:`/scripts/base/protocols/conn/index` scripts which supply the tracking
@ -242,9 +413,12 @@ more layers of information about a connection. This will give us a
chance to see the contents of the connection record without it being chance to see the contents of the connection record without it being
overly populated. overly populated.
.. btest:: connection-record-01 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/http/get.trace ${DOC_ROOT}/scripting/connection_record_01.bro $ bro -b -r http/get.trace connection_record_01.bro
[id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], orig=[size=136, state=5, num_pkts=7, num_bytes_ip=512, flow_label=0, l2_addr=c8:bc:c8:96:d2:a0], resp=[size=5007, state=5, num_pkts=7, num_bytes_ip=5379, flow_label=0, l2_addr=00:10:db:88:d2:ef], start_time=1362692526.869344, duration=0.211484, service={
}, history=ShADadFf, uid=CHhAvVGS1DHFjwGM9, tunnel=<uninitialized>, vlan=<uninitialized>, inner_vlan=<uninitialized>, conn=[ts=1362692526.869344, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], proto=tcp, service=<uninitialized>, duration=0.211484, orig_bytes=136, resp_bytes=5007, conn_state=SF, local_orig=<uninitialized>, local_resp=<uninitialized>, missed_bytes=0, history=ShADadFf, orig_pkts=7, orig_ip_bytes=512, resp_pkts=7, resp_ip_bytes=5379, tunnel_parents=<uninitialized>], extract_orig=F, extract_resp=F, thresholds=<uninitialized>]
As you can see from the output, the connection record is something of As you can see from the output, the connection record is something of
a jumble when printed on its own. Regularly taking a peek at a a jumble when printed on its own. Regularly taking a peek at a
@ -270,11 +444,21 @@ proper format of a dereferenced variable in scripts. In the output of
the script above, groups of information are collected between the script above, groups of information are collected between
brackets, which would correspond to the ``$``-delimiter in a Bro script. brackets, which would correspond to the ``$``-delimiter in a Bro script.
.. btest-include:: ${DOC_ROOT}/scripting/connection_record_02.bro .. literalinclude:: connection_record_02.bro
:caption:
:language: bro
:linenos:
.. btest:: connection-record-02 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -b -r ${TRACES}/http/get.trace ${DOC_ROOT}/scripting/connection_record_02.bro $bro -b -r http/get.trace connection_record_02.bro
[id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], orig=[size=136, state=5, num_pkts=7, num_bytes_ip=512, flow_label=0, l2_addr=c8:bc:c8:96:d2:a0], resp=[size=5007, state=5, num_pkts=7, num_bytes_ip=5379, flow_label=0, l2_addr=00:10:db:88:d2:ef], start_time=1362692526.869344, duration=0.211484, service={
}, history=ShADadFf, uid=CHhAvVGS1DHFjwGM9, tunnel=<uninitialized>, vlan=<uninitialized>, inner_vlan=<uninitialized>, conn=[ts=1362692526.869344, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], proto=tcp, service=<uninitialized>, duration=0.211484, orig_bytes=136, resp_bytes=5007, conn_state=SF, local_orig=<uninitialized>, local_resp=<uninitialized>, missed_bytes=0, history=ShADadFf, orig_pkts=7, orig_ip_bytes=512, resp_pkts=7, resp_ip_bytes=5379, tunnel_parents=<uninitialized>], extract_orig=F, extract_resp=F, thresholds=<uninitialized>, http=[ts=1362692526.939527, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], trans_depth=1, method=GET, host=bro.org, uri=/download/CHANGES.bro-aux.txt, referrer=<uninitialized>, version=1.1, user_agent=Wget/1.14 (darwin12.2.0), request_body_len=0, response_body_len=4705, status_code=200, status_msg=OK, info_code=<uninitialized>, info_msg=<uninitialized>, tags={
}, username=<uninitialized>, password=<uninitialized>, capture_password=F, proxied=<uninitialized>, range_request=F, orig_fuids=<uninitialized>, orig_filenames=<uninitialized>, orig_mime_types=<uninitialized>, resp_fuids=[FakNcS1Jfe01uljb3], resp_filenames=<uninitialized>, resp_mime_types=[text/plain], current_entity=<uninitialized>, orig_mime_depth=1, resp_mime_depth=1], http_state=[pending={
}, current_request=1, current_response=1, trans_depth=1]]
The addition of the ``base/protocols/http`` scripts populates the The addition of the ``base/protocols/http`` scripts populates the
``http=[]`` member of the connection record. While Bro is doing a ``http=[]`` member of the connection record. While Bro is doing a
@ -306,7 +490,10 @@ each of which produce the same result if ``EXPRESSION`` evaluates to the
same type as ``TYPE``. The decision as to which type of declaration to same type as ``TYPE``. The decision as to which type of declaration to
use is likely to be dictated by personal preference and readability. use is likely to be dictated by personal preference and readability.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_declaration.bro .. literalinclude:: data_type_declaration.bro
:caption:
:language: bro
:linenos:
Global Variables Global Variables
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
@ -347,13 +534,19 @@ decrypted from HTTP streams is stored in
:bro:see:`HTTP::default_capture_password` as shown in the stripped down :bro:see:`HTTP::default_capture_password` as shown in the stripped down
excerpt from :doc:`/scripts/base/protocols/http/main.bro` below. excerpt from :doc:`/scripts/base/protocols/http/main.bro` below.
.. btest-include:: ${DOC_ROOT}/scripting/http_main.bro .. literalinclude:: http_main.bro
:caption:
:language: bro
:linenos:
Because the constant was declared with the ``&redef`` attribute, if we Because the constant was declared with the ``&redef`` attribute, if we
needed to turn this option on globally, we could do so by adding the needed to turn this option on globally, we could do so by adding the
following line to our ``site/local.bro`` file before firing up Bro. following line to our ``site/local.bro`` file before firing up Bro.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_const_simple.bro .. literalinclude:: data_type_const_simple.bro
:caption:
:language: bro
:linenos:
While the idea of a re-definable constant might be odd, the constraint While the idea of a re-definable constant might be odd, the constraint
that constants can only be altered at parse-time remains even with the that constants can only be altered at parse-time remains even with the
@ -364,11 +557,18 @@ in a :bro:id:`bro_init` event. Were we to try to alter the table in
an event handler, Bro would notify the user of an error and the script an event handler, Bro would notify the user of an error and the script
would fail. would fail.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_const.bro .. literalinclude:: data_type_const.bro
:caption:
:language: bro
:linenos:
.. btest:: data_type_const.bro .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_type_const.bro $ bro -b data_type_const.bro
{
[80/tcp] = WWW,
[6666/tcp] = IRC
}
Local Variables Local Variables
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -382,7 +582,10 @@ of a script passes beyond that scope and no longer used, the variable
is deleted. Bro maintains names of locals separately from globally is deleted. Bro maintains names of locals separately from globally
visible ones, an example of which is illustrated below. visible ones, an example of which is illustrated below.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_local.bro .. literalinclude:: data_type_local.bro
:caption:
:language: bro
:linenos:
The script executes the event handler :bro:id:`bro_init` which in turn calls The script executes the event handler :bro:id:`bro_init` which in turn calls
the function ``add_two(i: count)`` with an argument of ``10``. Once Bro the function ``add_two(i: count)`` with an argument of ``10``. Once Bro
@ -455,7 +658,10 @@ for information that is already naturally unique such as ports or IP
addresses. The code snippet below shows both an explicit and implicit addresses. The code snippet below shows both an explicit and implicit
declaration of a locally scoped set. declaration of a locally scoped set.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro .. literalinclude:: data_struct_set_declaration.bro
:caption:
:language: bro
:linenos:
:lines: 1-4,22 :lines: 1-4,22
As you can see, sets are declared using the format ``SCOPE var_name: As you can see, sets are declared using the format ``SCOPE var_name:
@ -467,8 +673,12 @@ the ``in`` operator. In the case of iterating over a set, combining the
``for`` statement and the ``in`` operator will allow you to sequentially ``for`` statement and the ``in`` operator will allow you to sequentially
process each element of the set as seen below. process each element of the set as seen below.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro .. literalinclude:: data_struct_set_declaration.bro
:caption:
:language: bro
:linenos:
:lines: 17-21 :lines: 17-21
:lineno-start: 17
Here, the ``for`` statement loops over the contents of the set storing Here, the ``for`` statement loops over the contents of the set storing
each element in the temporary variable ``i``. With each iteration of each element in the temporary variable ``i``. With each iteration of
@ -487,16 +697,31 @@ negate the in operator itself. While the functionality is the same,
using the ``!in`` is more efficient as well as a more natural construct using the ``!in`` is more efficient as well as a more natural construct
which will aid in the readability of your script. which will aid in the readability of your script.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro .. literalinclude:: data_struct_set_declaration.bro
:caption:
:language: bro
:linenos:
:lines: 13-15 :lines: 13-15
:lineno-start: 13
You can see the full script and its output below. You can see the full script and its output below.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_set_declaration.bro .. literalinclude:: data_struct_set_declaration.bro
:caption:
:language: bro
:linenos:
.. btest:: data_struct_set_declaration .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_set_declaration.bro $ bro data_struct_set_declaration.bro
SSL Port: 22/tcp
SSL Port: 443/tcp
SSL Port: 587/tcp
SSL Port: 993/tcp
Non-SSL Port: 80/tcp
Non-SSL Port: 25/tcp
Non-SSL Port: 143/tcp
Non-SSL Port: 23/tcp
Tables Tables
~~~~~~ ~~~~~~
@ -505,11 +730,18 @@ A table in Bro is a mapping of a key to a value or yield. While the
values don't have to be unique, each key in the table must be unique values don't have to be unique, each key in the table must be unique
to preserve a one-to-one mapping of keys to values. to preserve a one-to-one mapping of keys to values.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_declaration.bro .. literalinclude:: data_struct_table_declaration.bro
:caption:
:language: bro
:linenos:
.. btest:: data_struct_table_declaration .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_table_declaration.bro $ bro data_struct_table_declaration.bro
Service Name: SSH - Common Port: 22/tcp
Service Name: HTTPS - Common Port: 443/tcp
Service Name: SMTPS - Common Port: 587/tcp
Service Name: IMAPS - Common Port: 993/tcp
In this example, In this example,
we've compiled a table of SSL-enabled services and their common we've compiled a table of SSL-enabled services and their common
@ -534,11 +766,18 @@ Bro implies a cost in complexity for the person writing the scripts
but pays off in effectiveness given the power of Bro as a network but pays off in effectiveness given the power of Bro as a network
security platform. security platform.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_table_complex.bro .. literalinclude:: data_struct_table_complex.bro
:caption:
:language: bro
:linenos:
.. btest:: data_struct_table_complex .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_table_complex.bro $ bro -b data_struct_table_complex.bro
Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai
Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai
Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada
Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai
This script shows a sample table of strings indexed by two This script shows a sample table of strings indexed by two
strings, a count, and a final string. With a tuple acting as an strings, a count, and a final string. With a tuple acting as an
@ -580,11 +819,18 @@ the vector name between two vertical pipes to get the vector's current
length before printing the contents of both Vectors and their current length before printing the contents of both Vectors and their current
lengths. lengths.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro .. literalinclude:: data_struct_vector_declaration.bro
:caption:
:language: bro
:linenos:
.. btest:: data_struct_vector_declaration .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_vector_declaration.bro $ bro data_struct_vector_declaration.bro
contents of v1: [1, 2, 3, 4]
length of v1: 4
contents of v2: [1, 2, 3, 4]
length of v2: 4
In a lot of cases, storing elements in a vector is simply a precursor In a lot of cases, storing elements in a vector is simply a precursor
to then iterating over them. Iterating over a vector is easy with the to then iterating over them. Iterating over a vector is easy with the
@ -595,12 +841,17 @@ called ``i`` which will hold the index of the current element in the
vector. Using ``i`` as an index to addr_vector we can access the vector. Using ``i`` as an index to addr_vector we can access the
current item in the vector with ``addr_vector[i]``. current item in the vector with ``addr_vector[i]``.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_vector_iter.bro .. literalinclude:: data_struct_vector_iter.bro
:caption:
:language: bro
:linenos:
.. btest:: data_struct_vector_iter .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -b ${DOC_ROOT}/scripting/data_struct_vector_iter.bro
$ bro -b data_struct_vector_iter.bro
1.2.0.0/18
2.3.0.0/18
3.4.0.0/18
Data Types Revisited Data Types Revisited
-------------------- --------------------
@ -653,7 +904,10 @@ your scripts. The following example below uses a Bro script to
determine if a series of IP addresses are within a set of subnets determine if a series of IP addresses are within a set of subnets
using a 20 bit subnet mask. using a 20 bit subnet mask.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_subnets.bro .. literalinclude:: data_type_subnets.bro
:caption:
:language: bro
:linenos:
Because this is a script that doesn't use any kind of network Because this is a script that doesn't use any kind of network
analysis, we can handle the event :bro:id:`bro_init` which is always analysis, we can handle the event :bro:id:`bro_init` which is always
@ -669,9 +923,13 @@ For example, ``10.0.0.1 in 10.0.0.0/8`` would return true while
script, we get the output listing the IP address and the subnet in script, we get the output listing the IP address and the subnet in
which it belongs. which it belongs.
.. btest:: data_type_subnets .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_subnets.bro $ bro data_type_subnets.bro
172.16.4.56 belongs to subnet 172.16.0.0/20
172.16.47.254 belongs to subnet 172.16.32.0/20
172.16.22.45 belongs to subnet 172.16.16.0/20
172.16.1.1 belongs to subnet 172.16.0.0/20
time time
~~~~ ~~~~
@ -693,14 +951,26 @@ timestamp and an indication of who the originator and responder were.
We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to We use the ``strftime`` format string of ``%Y%M%d %H:%m:%S`` to
produce a common date time formatted time stamp. produce a common date time formatted time stamp.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_time.bro .. literalinclude:: data_type_time.bro
:caption:
:language: bro
:linenos:
When the script is executed we get an output showing the details of When the script is executed we get an output showing the details of
established connections. established connections.
.. btest:: data_type_time .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_time.bro $ bro -r wikipedia.trace data_type_time.bro
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2\x0a
2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128\x0a
interval interval
~~~~~~~~ ~~~~~~~~
@ -730,15 +1000,35 @@ operator. The script below amends the script started in the section
above to include a time delta value printed along with the connection above to include a time delta value printed along with the connection
establishment report. establishment report.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_interval.bro .. literalinclude:: data_type_interval.bro
:caption:
:language: bro
:linenos:
This time, when we execute the script we see an additional line in the This time, when we execute the script we see an additional line in the
output to display the time delta since the last fully established output to display the time delta since the last fully established
connection. connection.
.. btest:: data_type_interval .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/wikipedia.trace ${DOC_ROOT}/scripting/data_type_interval.bro $ bro -r wikipedia.trace data_type_interval.bro
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 132.0 msecs 97.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 177.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 2.0 msecs 177.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 33.0 msecs 898.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 35.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 2.0 msecs 532.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2
Time since last connection: 7.0 msecs 866.0 usecs
2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128
Time since last connection: 817.0 msecs 703.0 usecs
Pattern Pattern
@ -755,7 +1045,10 @@ adheres to a strict format, requiring the regular expression or
pattern constant to be on the left side of the ``in`` operator and the pattern constant to be on the left side of the ``in`` operator and the
string against which it will be tested to be on the right. string against which it will be tested to be on the right.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_01.bro .. literalinclude:: data_type_pattern_01.bro
:caption:
:language: bro
:linenos:
In the sample above, two local variables are declared to hold our In the sample above, two local variables are declared to hold our
sample sentence and regular expression. Our regular expression in sample sentence and regular expression. Our regular expression in
@ -771,9 +1064,12 @@ excluding the actual matches. In this case, our pattern matches
twice, and results in a table with three entries. The ``print`` statements twice, and results in a table with three entries. The ``print`` statements
in the script will print the contents of the table in order. in the script will print the contents of the table in order.
.. btest:: data_type_pattern .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_01.bro $ bro data_type_pattern_01.bro
The
brown fox jumps over the
dog.
Patterns can also be used to compare strings using equality and Patterns can also be used to compare strings using equality and
inequality operators through the ``==`` and ``!=`` operators inequality operators through the ``==`` and ``!=`` operators
@ -783,13 +1079,13 @@ ternary conditional statements to illustrate the use of the ``==``
operator with patterns. The output is altered based operator with patterns. The output is altered based
on the result of the comparison between the pattern and the string. on the result of the comparison between the pattern and the string.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_pattern_02.bro .. literalinclude:: data_type_pattern_02.bro
.. btest:: data_type_pattern_02
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_type_pattern_02.bro
.. code-block:: console
$ bro data_type_pattern_02.bro
equality and /^?(equal)$?/ are not equal
equality and /^?(equality)$?/ are equal
Record Data Type Record Data Type
---------------- ----------------
@ -809,7 +1105,10 @@ example of the ``record`` data type in the earlier sections, the
:bro:type:`Conn::Info`, which corresponds to the fields logged into :bro:type:`Conn::Info`, which corresponds to the fields logged into
``conn.log``, is shown by the excerpt below. ``conn.log``, is shown by the excerpt below.
.. btest-include:: ${DOC_ROOT}/scripting/data_type_record.bro .. literalinclude:: data_type_record.bro
:caption:
:language: bro
:linenos:
Looking at the structure of the definition, a new collection of data Looking at the structure of the definition, a new collection of data
types is being defined as a type called ``Info``. Since this type types is being defined as a type called ``Info``. Since this type
@ -822,11 +1121,20 @@ that make up the record. The individual fields that make up the new
record are not limited in type or number as long as the name for each record are not limited in type or number as long as the name for each
field is unique. field is unique.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_record_01.bro .. literalinclude:: data_struct_record_01.bro
:caption:
:language: bro
:linenos:
.. btest:: data_struct_record_01 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_01.bro $ bro data_struct_record_01.bro
Service: dns(RFC1035)
port: 53/udp
port: 53/tcp
Service: http(RFC2616)
port: 8080/tcp
port: 80/tcp
The sample above shows a simple type definition that includes a The sample above shows a simple type definition that includes a
string, a set of ports, and a count to define a service type. Also string, a set of ports, and a count to define a service type. Also
@ -843,11 +1151,18 @@ records are even valid as fields within another record. We can extend
the example above to include another record that contains a Service the example above to include another record that contains a Service
record. record.
.. btest-include:: ${DOC_ROOT}/scripting/data_struct_record_02.bro .. literalinclude:: data_struct_record_02.bro
.. btest:: data_struct_record_02 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/data_struct_record_02.bro $ bro data_struct_record_02.bro
System: morlock
Service: http(RFC2616)
port: 8080/tcp
port: 80/tcp
Service: dns(RFC1035)
port: 53/udp
port: 53/tcp
The example above includes a second record type in which a field is The example above includes a second record type in which a field is
used as the data type for a set. Records can be repeatedly nested used as the data type for a set. Records can be repeatedly nested
@ -858,8 +1173,12 @@ It's also common to see a ``type`` used to simply alias a data
structure to a more descriptive name. The example below shows an structure to a more descriptive name. The example below shows an
example of this from Bro's own type definitions file. example of this from Bro's own type definitions file.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/init-bare.bro .. code-block:: bro
:lines: 12,19,26 :caption: init-bare.bro
type string_array: table[count] of string;
type string_set: set[string];
type addr_set: set[addr];
The three lines above alias a type of data structure to a descriptive The three lines above alias a type of data structure to a descriptive
name. Functionally, the operations are the same, however, each of the name. Functionally, the operations are the same, however, each of the
@ -916,11 +1235,24 @@ It's always best to work through the problem once, simulating the
desired output with ``print`` and ``fmt`` before attempting to dive desired output with ``print`` and ``fmt`` before attempting to dive
into the Logging Framework. into the Logging Framework.
.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro .. literalinclude:: framework_logging_factorial_01.bro
:caption:
:language: bro
:linenos:
.. btest:: framework_logging_factorial .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_01.bro $ bro framework_logging_factorial_01.bro
1
2
6
24
120
720
5040
40320
362880
3628800
This script defines a factorial function to recursively calculate the This script defines a factorial function to recursively calculate the
factorial of a unsigned integer passed as an argument to the function. Using factorial of a unsigned integer passed as an argument to the function. Using
@ -930,7 +1262,10 @@ calculations correctly as well get an idea of the answers ourselves.
The output of the script aligns with what we expect so now it's time The output of the script aligns with what we expect so now it's time
to integrate the Logging Framework. to integrate the Logging Framework.
.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro .. literalinclude:: framework_logging_factorial_02.bro
:caption:
:language: bro
:linenos:
As mentioned above we have to perform a few steps before we can As mentioned above we have to perform a few steps before we can
issue the :bro:id:`Log::write` method and produce a logfile. issue the :bro:id:`Log::write` method and produce a logfile.
@ -962,10 +1297,29 @@ Now, if we run this script, instead of generating
logging information to stdout, no output is created. Instead the logging information to stdout, no output is created. Instead the
output is all in ``factor.log``, properly formatted and organized. output is all in ``factor.log``, properly formatted and organized.
.. btest:: framework_logging_factorial-2 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_02.bro $ bro framework_logging_factorial_02.bro
@TEST-EXEC: btest-rst-include factor.log $ cat factor.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path factor
#open 2018-12-14-21-47-18
#fields num factorial_num
#types count count
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
#close 2018-12-14-21-47-18
While the previous example is a simplistic one, it serves to While the previous example is a simplistic one, it serves to
demonstrate the small pieces of script code hat need to be in place in demonstrate the small pieces of script code hat need to be in place in
@ -993,7 +1347,10 @@ example we've been using, let's extend it so as to write any factorial
which is a factor of 5 to an alternate file, while writing the which is a factor of 5 to an alternate file, while writing the
remaining logs to factor.log. remaining logs to factor.log.
.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro .. literalinclude:: framework_logging_factorial_03.bro
:caption:
:language: bro
:linenos:
To dynamically alter the file in which a stream writes its logs, a To dynamically alter the file in which a stream writes its logs, a
filter can specify a function that returns a string to be used as the filter can specify a function that returns a string to be used as the
@ -1014,10 +1371,25 @@ factorials that are a factors of 5, ``factor-non5.log`` with the
factorials that are not factors of 5, and ``factor.log`` which would have factorials that are not factors of 5, and ``factor.log`` which would have
included all factorials. included all factorials.
.. btest:: framework_logging_factorial-3 .. code-block:: console
@TEST-EXEC: btest-rst-cmd bro ${DOC_ROOT}/scripting/framework_logging_factorial_03.bro $ bro framework_logging_factorial_03.bro
@TEST-EXEC: btest-rst-include factor-mod5.log $ cat factor-mod5.log
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path factor-mod5
#open 2018-12-14-21-47-18
#fields num factorial_num
#types count count
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
#close 2018-12-14-21-47-1
The ability of Bro to generate easily customizable and extensible logs The ability of Bro to generate easily customizable and extensible logs
which remain easily parsable is a big part of the reason Bro has which remain easily parsable is a big part of the reason Bro has
@ -1047,7 +1419,10 @@ block and define the value to be passed to it, in this case the
``Factor::Info`` record. We then list the ``log_factor`` function as ``Factor::Info`` record. We then list the ``log_factor`` function as
the ``$ev`` field in the call to ``Log::create_stream`` the ``$ev`` field in the call to ``Log::create_stream``
.. btest-include:: ${DOC_ROOT}/scripting/framework_logging_factorial_04.bro .. literalinclude:: framework_logging_factorial_04.bro
:caption:
:language: bro
:linenos:
Raising Notices Raising Notices
@ -1098,8 +1473,60 @@ or not that notice is acted upon is decided by the local Notice
Policy, but the script attempts to supply as much information as Policy, but the script attempts to supply as much information as
possible while staying concise. possible while staying concise.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssh/interesting-hostnames.bro .. code-block:: bro
:lines: 1-52 :caption: scripts/policy/protocols/ssh/interesting-hostnames.bro
##! This script will generate a notice if an apparent SSH login originates
##! or heads to a host with a reverse hostname that looks suspicious. By
##! default, the regular expression to match "interesting" hostnames includes
##! names that are typically used for infrastructure hosts like nameservers,
##! mail servers, web servers and ftp servers.
@load base/frameworks/notice
module SSH;
export {
redef enum Notice::Type += {
## Generated if a login originates or responds with a host where
## the reverse hostname lookup resolves to a name matched by the
## :bro:id:`SSH::interesting_hostnames` regular expression.
Interesting_Hostname_Login,
};
## Strange/bad host names to see successful SSH logins from or to.
option interesting_hostnames =
/^d?ns[0-9]*\./ |
/^smtp[0-9]*\./ |
/^mail[0-9]*\./ |
/^pop[0-9]*\./ |
/^imap[0-9]*\./ |
/^www[0-9]*\./ |
/^ftp[0-9]*\./;
}
function check_ssh_hostname(id: conn_id, uid: string, host: addr)
{
when ( local hostname = lookup_addr(host) )
{
if ( interesting_hostnames in hostname )
{
NOTICE([$note=Interesting_Hostname_Login,
$msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.",
Site::is_local_addr(host) ? "local" : "remote",
host == id$orig_h ? "client" : "server"),
$sub=hostname, $id=id, $uid=uid]);
}
}
}
event ssh_auth_successful(c: connection, auth_method_none: bool)
{
for ( host in set(c$id$orig_h, c$id$resp_h) )
{
check_ssh_hostname(c$id, c$uid, host);
}
}
While much of the script relates to the actual detection, the parts While much of the script relates to the actual detection, the parts
specific to the Notice Framework are actually quite interesting in specific to the Notice Framework are actually quite interesting in
@ -1137,7 +1564,10 @@ action based on the answer. The hook below adds the
``SSH::Interesting_Hostname_Login`` notice raised in the ``SSH::Interesting_Hostname_Login`` notice raised in the
:doc:`/scripts/policy/protocols/ssh/interesting-hostnames.bro` script. :doc:`/scripts/policy/protocols/ssh/interesting-hostnames.bro` script.
.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_01.bro .. literalinclude:: framework_notice_hook_01.bro
:caption:
:language: bro
:linenos:
In the example above we've added ``Notice::ACTION_EMAIL`` to the In the example above we've added ``Notice::ACTION_EMAIL`` to the
``n$actions`` set. This set, defined in the Notice Framework scripts, ``n$actions`` set. This set, defined in the Notice Framework scripts,
@ -1174,8 +1604,14 @@ identifier. An identifier is a unique string of information collected
from the connection relative to the behavior that has been observed by from the connection relative to the behavior that has been observed by
Bro. Bro.
.. btest-include:: ${BRO_SRC_ROOT}/scripts/policy/protocols/ssl/expiring-certs.bro .. code-block:: bro
:lines: 64-68 :caption: scripts/policy/protocols/ssl/expiring-certs.bro
NOTICE([$note=Certificate_Expires_Soon,
$msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after),
$conn=c, $suppress_for=1day,
$identifier=cat(c$id$resp_h, c$id$resp_p, hash),
$fuid=fuid]);
In the :doc:`/scripts/policy/protocols/ssl/expiring-certs.bro` script In the :doc:`/scripts/policy/protocols/ssl/expiring-certs.bro` script
which identifies when SSL certificates are set to expire and raises which identifies when SSL certificates are set to expire and raises
@ -1206,7 +1642,10 @@ environment in which it is be run. Using the example of
``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for`` ``SSL::Certificate_Expires_Soon`` to configure the ``$suppress_for``
variable to a shorter time. variable to a shorter time.
.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_hook_suppression_01.bro .. literalinclude:: framework_notice_hook_suppression_01.bro
:caption:
:language: bro
:linenos:
While ``Notice::policy`` hooks allow you to build custom While ``Notice::policy`` hooks allow you to build custom
predicate-based policies for a deployment, there are bound to be times predicate-based policies for a deployment, there are bound to be times
@ -1253,11 +1692,17 @@ suppression from a notice while ``Notice::type_suppression_intervals``
can be used to alter the suppression interval defined by $suppress_for can be used to alter the suppression interval defined by $suppress_for
in the call to ``NOTICE``. in the call to ``NOTICE``.
.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_01.bro .. literalinclude:: framework_notice_shortcuts_01.bro
:caption:
:language: bro
:linenos:
The Notice Policy shortcut above adds the ``Notice::Type`` of The Notice Policy shortcut above adds the ``Notice::Type`` of
``SSH::Interesting_Hostname_Login`` to the ``SSH::Interesting_Hostname_Login`` to the
``Notice::emailed_types`` set while the shortcut below alters the length ``Notice::emailed_types`` set while the shortcut below alters the length
of time for which those notices will be suppressed. of time for which those notices will be suppressed.
.. btest-include:: ${DOC_ROOT}/scripting/framework_notice_shortcuts_02.bro .. literalinclude:: framework_notice_shortcuts_02.bro
:caption:
:language: bro
:linenos:

View file

@ -1,26 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r tls/tls-expired-cert.trace conditional-notice.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 2017-12-21-02-23-46
#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
1394745603.293028 CHhAvVGS1DHFjwGM9 192.168.4.149 60539 87.98.220.10 443 F1fX1R2cDOzbvg17ye - - tcp SSL::Certificate_Expired Certificate CN=www.spidh.org,OU=COMODO SSL,OU=Domain Control Validated expired at 2014-03-04-23:59:59.000000000 - 192.168.4.149 87.98.220.10 443 - - Notice::ACTION_EMAIL,Notice::ACTION_LOG 86400.000000 F - - - - -
#close 2017-12-21-02-23-46

View file

@ -1,11 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -b -r http/get.trace connection_record_01.bro
[id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], orig=[size=136, state=5, num_pkts=7, num_bytes_ip=512, flow_label=0, l2_addr=c8:bc:c8:96:d2:a0], resp=[size=5007, state=5, num_pkts=7, num_bytes_ip=5379, flow_label=0, l2_addr=00:10:db:88:d2:ef], start_time=1362692526.869344, duration=0.211484, service={
}, history=ShADadFf, uid=CHhAvVGS1DHFjwGM9, tunnel=<uninitialized>, vlan=<uninitialized>, inner_vlan=<uninitialized>, conn=[ts=1362692526.869344, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], proto=tcp, service=<uninitialized>, duration=0.211484, orig_bytes=136, resp_bytes=5007, conn_state=SF, local_orig=<uninitialized>, local_resp=<uninitialized>, missed_bytes=0, history=ShADadFf, orig_pkts=7, orig_ip_bytes=512, resp_pkts=7, resp_ip_bytes=5379, tunnel_parents=<uninitialized>], extract_orig=F, extract_resp=F, thresholds=<uninitialized>]

View file

@ -1,15 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -b -r http/get.trace connection_record_02.bro
[id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], orig=[size=136, state=5, num_pkts=7, num_bytes_ip=512, flow_label=0, l2_addr=c8:bc:c8:96:d2:a0], resp=[size=5007, state=5, num_pkts=7, num_bytes_ip=5379, flow_label=0, l2_addr=00:10:db:88:d2:ef], start_time=1362692526.869344, duration=0.211484, service={
}, history=ShADadFf, uid=CHhAvVGS1DHFjwGM9, tunnel=<uninitialized>, vlan=<uninitialized>, inner_vlan=<uninitialized>, conn=[ts=1362692526.869344, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], proto=tcp, service=<uninitialized>, duration=0.211484, orig_bytes=136, resp_bytes=5007, conn_state=SF, local_orig=<uninitialized>, local_resp=<uninitialized>, missed_bytes=0, history=ShADadFf, orig_pkts=7, orig_ip_bytes=512, resp_pkts=7, resp_ip_bytes=5379, tunnel_parents=<uninitialized>], extract_orig=F, extract_resp=F, thresholds=<uninitialized>, http=[ts=1362692526.939527, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp], trans_depth=1, method=GET, host=bro.org, uri=/download/CHANGES.bro-aux.txt, referrer=<uninitialized>, version=1.1, user_agent=Wget/1.14 (darwin12.2.0), request_body_len=0, response_body_len=4705, status_code=200, status_msg=OK, info_code=<uninitialized>, info_msg=<uninitialized>, tags={
}, username=<uninitialized>, password=<uninitialized>, capture_password=F, proxied=<uninitialized>, range_request=F, orig_fuids=<uninitialized>, orig_filenames=<uninitialized>, orig_mime_types=<uninitialized>, resp_fuids=[FakNcS1Jfe01uljb3], resp_filenames=<uninitialized>, resp_mime_types=[text/plain], current_entity=<uninitialized>, orig_mime_depth=1, resp_mime_depth=1], http_state=[pending={
}, current_request=1, current_response=1, trans_depth=1]]

View file

@ -1,14 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_struct_record_01.bro
Service: dns(RFC1035)
port: 53/udp
port: 53/tcp
Service: http(RFC2616)
port: 8080/tcp
port: 80/tcp

View file

@ -1,15 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_struct_record_02.bro
System: morlock
Service: http(RFC2616)
port: 8080/tcp
port: 80/tcp
Service: dns(RFC1035)
port: 53/udp
port: 53/tcp

View file

@ -1,16 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_struct_set_declaration.bro
SSL Port: 22/tcp
SSL Port: 443/tcp
SSL Port: 587/tcp
SSL Port: 993/tcp
Non-SSL Port: 80/tcp
Non-SSL Port: 25/tcp
Non-SSL Port: 143/tcp
Non-SSL Port: 23/tcp

View file

@ -1,12 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -b data_struct_table_complex.bro
Harakiri was released in 1962 by Shochiku Eiga studios, directed by Masaki Kobayashi and starring Tatsuya Nakadai
Goyokin was released in 1969 by Fuji studios, directed by Hideo Gosha and starring Tatsuya Nakadai
Tasogare Seibei was released in 2002 by Eisei Gekijo studios, directed by Yoji Yamada and starring Hiroyuki Sanada
Kiru was released in 1968 by Toho studios, directed by Kihachi Okamoto and starring Tatsuya Nakadai

View file

@ -1,12 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_struct_table_declaration.bro
Service Name: SSH - Common Port: 22/tcp
Service Name: HTTPS - Common Port: 443/tcp
Service Name: SMTPS - Common Port: 587/tcp
Service Name: IMAPS - Common Port: 993/tcp

View file

@ -1,12 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_struct_vector_declaration.bro
contents of v1: [1, 2, 3, 4]
length of v1: 4
contents of v2: [1, 2, 3, 4]
length of v2: 4

View file

@ -1,11 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -b data_struct_vector_iter.bro
1.2.0.0/18
2.3.0.0/18
3.4.0.0/18

View file

@ -1,12 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -b data_type_const.bro
{
[80/tcp] = WWW,
[6666/tcp] = IRC
}

View file

@ -1,25 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r wikipedia.trace data_type_interval.bro
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 132.0 msecs 97.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 177.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 2.0 msecs 177.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 33.0 msecs 898.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 35.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3
Time since last connection: 2.0 msecs 532.0 usecs
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2
Time since last connection: 7.0 msecs 866.0 usecs
2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128
Time since last connection: 817.0 msecs 703.0 usecs

View file

@ -1,11 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_type_pattern_01.bro
The
brown fox jumps over the
dog.

View file

@ -1,10 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_type_pattern_02.bro
equality and /^?(equal)$?/ are not equal
equality and /^?(equality)$?/ are equal

View file

@ -1,12 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro data_type_subnets.bro
172.16.4.56 belongs to subnet 172.16.0.0/20
172.16.47.254 belongs to subnet 172.16.32.0/20
172.16.22.45 belongs to subnet 172.16.16.0/20
172.16.1.1 belongs to subnet 172.16.0.0/20

View file

@ -1,17 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r wikipedia.trace data_type_time.bro
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.118\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.3\x0a
2011/06/18 19:03:08: New connection established from 141.142.220.118 to 208.80.152.2\x0a
2011/06/18 19:03:09: New connection established from 141.142.220.235 to 173.192.163.128\x0a

View file

@ -1,17 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/get.trace file_analysis_01.bro
file_state_remove
FakNcS1Jfe01uljb3
CHhAvVGS1DHFjwGM9
[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp]
HTTP
connection_state_remove
CHhAvVGS1DHFjwGM9
[orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp]
HTTP

View file

@ -1,10 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/get.trace file_analysis_02.bro
new file, FakNcS1Jfe01uljb3
file_hash, FakNcS1Jfe01uljb3, md5, 397168fd09991a0e712254df7bc639ac

View file

@ -1,11 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro file_analysis_03.bro
new file, FZedLu4Ajcvge02jA8
file_hash, FZedLu4Ajcvge02jA8, md5, f0ef7081e1539ac00ef5b761b4fb01b3
file_state_remove

View file

@ -1,14 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/bro.org.pcap file_extraction.bro
Extracting file HTTP-FiIpIB2hRQSDBOSJRg.html
Extracting file HTTP-FMG4bMmVV64eOsCb.txt
Extracting file HTTP-FnaT2a3UDd093opCB9.txt
Extracting file HTTP-FfQGqj4Fhh3pH7nVQj.txt
Extracting file HTTP-FsvATF146kf1Emc21j.txt
[...]

View file

@ -1,33 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro framework_logging_factorial_02.bro
.. rst-class:: btest-include
.. code-block:: guess
:linenos:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path factor
#open 2013-10-07-23-48-11
#fields num factorial_num
#types count count
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
#close 2013-10-07-23-48-11

View file

@ -1,29 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro framework_logging_factorial_03.bro
.. rst-class:: btest-include
.. code-block:: guess
:linenos:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path factor-mod5
#open 2013-10-07-23-48-12
#fields num factorial_num
#types count count
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
#close 2013-10-07-23-48-12

View file

@ -1,18 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro framework_logging_factorial_01.bro
1
2
6
24
120
720
5040
40320
362880
3628800

View file

@ -1,24 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r ftp/bruteforce.pcap protocols/ftp/detect-bruteforcing.bro
.. rst-class:: btest-include
.. code-block:: guess
:linenos:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2017-12-21-02-24-08
#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
1389721084.522861 - - - - - - - - - FTP::Bruteforcing 192.168.56.1 had 20 failed logins on 1 FTP server in 0m37s - 192.168.56.1 - - - - Notice::ACTION_LOG 3600.000000 F - - - - -
#close 2017-12-21-02-24-08

View file

@ -1,9 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/proxy.pcap http_proxy_01.bro
A local server is acting as an open proxy: 192.168.56.101

View file

@ -1,9 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/proxy.pcap http_proxy_02.bro
A local server is acting as an open proxy: 192.168.56.101

View file

@ -1,9 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/proxy.pcap http_proxy_03.bro
A local server is acting as an open proxy: 192.168.56.101

View file

@ -1,24 +0,0 @@
.. rst-class:: btest-cmd
.. code-block:: none
:linenos:
:emphasize-lines: 1,1
# bro -r http/proxy.pcap http_proxy_04.bro
.. rst-class:: btest-include
.. code-block:: guess
:linenos:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2017-12-21-02-24-33
#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
1389654450.449603 CHhAvVGS1DHFjwGM9 192.168.56.1 52679 192.168.56.101 80 - - - tcp HTTP::Open_Proxy A local server is acting as an open proxy: 192.168.56.101 - 192.168.56.1 192.168.56.101 80 - - Notice::ACTION_LOG 86400.000000 F - - - - -
#close 2017-12-21-02-24-33

View file

@ -1,30 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
Bro_DNS.events.bif.bro
## Generated for DNS requests. For requests with multiple queries, this event
## is raised once for each.
##
## See `Wikipedia <http://en.wikipedia.org/wiki/Domain_Name_System>`__ for more
## information about the DNS protocol. Bro analyzes both UDP and TCP DNS
## sessions.
##
## c: The connection, which may be UDP or TCP depending on the type of the
## transport-layer session being analyzed.
##
## msg: The parsed DNS message header.
##
## query: The queried name.
##
## qtype: The queried resource record type.
##
## qclass: The queried resource record class.
##
## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end
## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
global dns_request: event(c: connection , msg: dns_msg , query: string , qtype: count , qclass: count );

View file

@ -1,16 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
connecting-connector.bro
redef exit_only_after_terminate = T;
event bro_init()
{
Broker::peer("127.0.0.1");
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added", endpoint;
terminate();
}

View file

@ -1,21 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
connecting-listener.bro
redef exit_only_after_terminate = T;
event bro_init()
{
Broker::listen("127.0.0.1");
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added", endpoint;
}
event Broker::peer_lost(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer lost", endpoint;
terminate();
}

View file

@ -1,39 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
events-connector.bro
redef exit_only_after_terminate = T;
global my_event: event(msg: string, c: count);
global my_auto_event: event(msg: string, c: count);
event bro_init()
{
Broker::peer("127.0.0.1");
Broker::auto_publish("bro/event/my_auto_event", my_auto_event);
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added", endpoint;
Broker::publish("bro/event/my_event", my_event, "hi", 0);
event my_auto_event("stuff", 88);
Broker::publish("bro/event/my_event", my_event, "...", 1);
event my_auto_event("more stuff", 51);
local e = Broker::make_event(my_event, "bye", 2);
Broker::publish("bro/event/my_event", e);
}
event Broker::peer_lost(endpoint: Broker::EndpointInfo, msg: string)
{
terminate();
}
event my_event(msg: string, c: count)
{
print "got my_event", msg, c;
}
event my_auto_event(msg: string, c: count)
{
print "got my_auto_event", msg, c;
}

View file

@ -1,37 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
events-listener.bro
redef exit_only_after_terminate = T;
global msg_count = 0;
global my_event: event(msg: string, c: count);
global my_auto_event: event(msg: string, c: count);
event bro_init()
{
Broker::subscribe("bro/event/");
Broker::listen("127.0.0.1");
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added", endpoint;
}
event my_event(msg: string, c: count)
{
++msg_count;
print "got my_event", msg, c;
if ( msg_count == 5 )
terminate();
}
event my_auto_event(msg: string, c: count)
{
++msg_count;
print "got my_auto_event", msg, c;
if ( msg_count == 5 )
terminate();
}

View file

@ -1,40 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
logs-connector.bro
@load ./testlog
redef exit_only_after_terminate = T;
global n = 0;
event bro_init()
{
Broker::peer("127.0.0.1");
}
event do_write()
{
if ( n == 6 )
return;
Log::write(Test::LOG, [$msg = "ping", $num = n]);
++n;
event do_write();
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added", endpoint;
event do_write();
}
event Broker::peer_lost(endpoint: Broker::EndpointInfo, msg: string)
{
terminate();
}
event Test::log_test(rec: Test::Info)
{
print "wrote log", rec;
Broker::publish("bro/logs/forward/test", Test::log_test, rec);
}

View file

@ -1,26 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
logs-listener.bro
@load ./testlog
redef exit_only_after_terminate = T;
event bro_init()
{
Broker::subscribe("bro/logs");
Broker::listen("127.0.0.1");
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added", endpoint;
}
event Test::log_test(rec: Test::Info)
{
print "got log event", rec;
if ( rec$num == 5 )
terminate();
}

View file

@ -1,33 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
stores-connector.bro
redef exit_only_after_terminate = T;
global h: opaque of Broker::Store;
global ready: event();
event Broker::peer_lost(endpoint: Broker::EndpointInfo, msg: string)
{
terminate();
}
event bro_init()
{
h = Broker::create_master("mystore");
local myset: set[string] = {"a", "b", "c"};
local myvec: vector of string = {"alpha", "beta", "gamma"};
Broker::put(h, "one", 110);
Broker::put(h, "two", 223);
Broker::put(h, "myset", myset);
Broker::put(h, "myvec", myvec);
Broker::increment(h, "one");
Broker::decrement(h, "two");
Broker::insert_into_set(h, "myset", "d");
Broker::remove_from(h, "myset", "b");
Broker::push(h, "myvec", "delta");
Broker::peer("127.0.0.1");
}

View file

@ -1,83 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
stores-listener.bro
redef exit_only_after_terminate = T;
global h: opaque of Broker::Store;
global expected_key_count = 4;
global key_count = 0;
# Lookup a value in the store based on an arbitrary key string.
function do_lookup(key: string)
{
when ( local res = Broker::get(h, key) )
{
++key_count;
print "lookup", key, res;
# End after we iterated over looking up each key in the store twice.
if ( key_count == expected_key_count * 2 )
terminate();
}
# All data store queries must specify a timeout
timeout 3sec
{ print "timeout", key; }
}
event check_keys()
{
# Here we just query for the list of keys in the store, and show how to
# look up each one's value.
when ( local res = Broker::keys(h) )
{
print "clone keys", res;
if ( res?$result )
{
# Since we know that the keys we are storing are all strings,
# we can conveniently cast the result of Broker::keys to
# a native Bro type, namely 'set[string]'.
for ( k in res$result as string_set )
do_lookup(k);
# Alternatively, we can use a generic iterator to iterate
# over the results (which we know is of the 'set' type because
# that's what Broker::keys() always returns). If the keys
# we stored were not all of the same type, then you would
# likely want to use this method of inspecting the store's keys.
local i = Broker::set_iterator(res$result);
while ( ! Broker::set_iterator_last(i) )
{
do_lookup(Broker::set_iterator_value(i) as string);
Broker::set_iterator_next(i);
}
}
}
# All data store queries must specify a timeout.
# You also might see timeouts on connecting/initializing a clone since
# it hasn't had time to get fully set up yet.
timeout 1sec
{
print "timeout";
schedule 1sec { check_keys() };
}
}
event Broker::peer_added(endpoint: Broker::EndpointInfo, msg: string)
{
print "peer added";
# We could create a clone early, like in bro_init and it will periodically
# try to synchronize with its master once it connects, however, we just
# create it now since we know the peer w/ the master store has just
# connected.
h = Broker::create_clone("mystore");
event check_keys();
}
event bro_init()
{
Broker::listen("127.0.0.1");
}

View file

@ -1,21 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
testlog.bro
module Test;
export {
redef enum Log::ID += { LOG };
type Info: record {
msg: string &log;
num: count &log;
};
global log_test: event(rec: Test::Info);
}
event bro_init() &priority=5
{
Log::create_stream(Test::LOG, [$columns=Test::Info, $ev=log_test, $path="test"]);
}

View file

@ -1,24 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
file_analysis_01.bro
event connection_state_remove(c: connection)
{
print "connection_state_remove";
print c$uid;
print c$id;
for ( s in c$service )
print s;
}
event file_state_remove(f: fa_file)
{
print "file_state_remove";
print f$id;
for ( cid in f$conns )
{
print f$conns[cid]$uid;
print cid;
}
print f$source;
}

View file

@ -1,16 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
file_analysis_02.bro
event file_sniff(f: fa_file, meta: fa_metadata)
{
if ( ! meta?$mime_type ) return;
print "new file", f$id;
if ( meta$mime_type == "text/plain" )
Files::add_analyzer(f, Files::ANALYZER_MD5);
}
event file_hash(f: fa_file, kind: string, hash: string)
{
print "file_hash", f$id, kind, hash;
}

View file

@ -1,29 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
file_analysis_03.bro
redef exit_only_after_terminate = T;
event file_new(f: fa_file)
{
print "new file", f$id;
Files::add_analyzer(f, Files::ANALYZER_MD5);
}
event file_state_remove(f: fa_file)
{
print "file_state_remove";
Input::remove(f$source);
terminate();
}
event file_hash(f: fa_file, kind: string, hash: string)
{
print "file_hash", f$id, kind, hash;
}
event bro_init()
{
local source: string = "./myfile";
Input::add_analysis([$source=source, $name=source]);
}

View file

@ -1,14 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-1-drop-with-debug.bro
event NetControl::init()
{
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
event connection_established(c: connection)
{
NetControl::drop_connection(c$id, 20 secs);
}

View file

@ -1,14 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-10-use-skeleton.bro
event NetControl::init()
{
local skeleton_plugin = NetControl::create_skeleton("");
NetControl::activate(skeleton_plugin, 0);
}
event connection_established(c: connection)
{
NetControl::drop_connection(c$id, 20 secs);
}

View file

@ -1,20 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-2-ssh-guesser.bro
@load protocols/ssh/detect-bruteforcing
redef SSH::password_guesses_limit=10;
event NetControl::init()
{
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
hook Notice::policy(n: Notice::Info)
{
if ( n$note == SSH::Password_Guessing )
NetControl::drop_address(n$src, 60min);
}

View file

@ -1,20 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-3-ssh-guesser.bro
@load protocols/ssh/detect-bruteforcing
redef SSH::password_guesses_limit=10;
event NetControl::init()
{
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
hook Notice::policy(n: Notice::Info)
{
if ( n$note == SSH::Password_Guessing )
add n$actions[Notice::ACTION_DROP];
}

View file

@ -1,30 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-4-drop.bro
function our_drop_connection(c: conn_id, t: interval)
{
# As a first step, create the NetControl::Entity that we want to block
local e = NetControl::Entity($ty=NetControl::CONNECTION, $conn=c);
# Then, use the entity to create the rule to drop the entity in the forward path
local r = NetControl::Rule($ty=NetControl::DROP,
$target=NetControl::FORWARD, $entity=e, $expire=t);
# Add the rule
local id = NetControl::add_rule(r);
if ( id == "" )
print "Error while dropping";
}
event NetControl::init()
{
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
event connection_established(c: connection)
{
our_drop_connection(c$id, 20 secs);
}

View file

@ -1,26 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-5-hook.bro
hook NetControl::rule_policy(r: NetControl::Rule)
{
if ( r$ty == NetControl::DROP &&
r$entity$ty == NetControl::CONNECTION &&
r$entity$conn$orig_h in 192.168.0.0/16 )
{
print "Ignored connection from", r$entity$conn$orig_h;
break;
}
}
event NetControl::init()
{
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
event connection_established(c: connection)
{
NetControl::drop_connection(c$id, 20 secs);
}

View file

@ -1,21 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-6-find.bro
event NetControl::init()
{
local netcontrol_debug = NetControl::create_debug(T);
NetControl::activate(netcontrol_debug, 0);
}
event connection_established(c: connection)
{
if ( |NetControl::find_rules_addr(c$id$orig_h)| > 0 )
{
print "Rule already exists";
return;
}
NetControl::drop_connection(c$id, 20 secs);
print "Rule added";
}

View file

@ -1,14 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-7-catch-release.bro
event NetControl::init()
{
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
}
event connection_established(c: connection)
{
NetControl::drop_address_catch_release(c$id$orig_h);
}

View file

@ -1,33 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-8-multiple.bro
function our_openflow_check(p: NetControl::PluginState, r: NetControl::Rule): bool
{
if ( r$ty == NetControl::DROP &&
r$entity$ty == NetControl::ADDRESS &&
subnet_width(r$entity$ip) == 32 &&
subnet_to_addr(r$entity$ip) in 192.168.17.0/24 )
return F;
return T;
}
event NetControl::init()
{
# Add debug plugin with low priority
local debug_plugin = NetControl::create_debug(T);
NetControl::activate(debug_plugin, 0);
# Instantiate OpenFlow debug plugin with higher priority
local of_controller = OpenFlow::log_new(42);
local netcontrol_of = NetControl::create_openflow(of_controller, [$check_pred=our_openflow_check]);
NetControl::activate(netcontrol_of, 10);
}
event NetControl::init_done()
{
NetControl::drop_address(10.0.0.1, 1min);
NetControl::drop_address(192.168.17.2, 1min);
NetControl::drop_address(192.168.18.2, 1min);
}

View file

@ -1,43 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
netcontrol-9-skeleton.bro
module NetControl;
export {
## Instantiates the plugin.
global create_skeleton: function(argument: string) : PluginState;
}
function skeleton_name(p: PluginState) : string
{
return "NetControl skeleton plugin";
}
function skeleton_add_rule_fun(p: PluginState, r: Rule) : bool
{
print "add", r;
event NetControl::rule_added(r, p);
return T;
}
function skeleton_remove_rule_fun(p: PluginState, r: Rule, reason: string &default="") : bool
{
print "remove", r;
event NetControl::rule_removed(r, p);
return T;
}
global skeleton_plugin = Plugin(
$name = skeleton_name,
$can_expire = F,
$add_rule = skeleton_add_rule_fun,
$remove_rule = skeleton_remove_rule_fun
);
function create_skeleton(argument: string) : PluginState
{
local p = PluginState($plugin=skeleton_plugin);
return p;
}

View file

@ -1,14 +0,0 @@
# @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];
}

View file

@ -1,16 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
sqlite-conn-filter.bro
event bro_init()
{
local filter: Log::Filter =
[
$name="sqlite",
$path="/var/db/conn",
$config=table(["tablename"] = "conn"),
$writer=Log::WRITER_SQLITE
];
Log::add_filter(Conn::LOG, filter);
}

View file

@ -1,44 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
sqlite-read-events.bro
@load frameworks/files/hash-all-files
type Val: record {
hash: string;
description: string;
};
event line(description: Input::EventDescription, tpe: Input::Event, r: Val)
{
print fmt("malware-hit with hash %s, description %s", r$hash, r$description);
}
global malware_source = "/var/db/malware";
event file_hash(f: fa_file, kind: string, hash: string)
{
# check all sha1 hashes
if ( kind=="sha1" )
{
Input::add_event(
[
$source=malware_source,
$name=hash,
$fields=Val,
$ev=line,
$want_record=T,
$config=table(
["query"] = fmt("select * from malware_hashes where hash='%s';", hash)
),
$reader=Input::READER_SQLITE
]);
}
}
event Input::end_of_data(name: string, source:string)
{
if ( source == malware_source )
Input::remove(name);
}

View file

@ -1,39 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
sqlite-read-table.bro
type Idx: record {
host: addr;
};
type Val: record {
users: set[string];
};
global hostslist: table[addr] of Val = table();
event bro_init()
{
Input::add_table([$source="/var/db/hosts",
$name="hosts",
$idx=Idx,
$val=Val,
$destination=hostslist,
$reader=Input::READER_SQLITE,
$config=table(["query"] = "select * from machines_to_users;")
]);
Input::remove("hosts");
}
event Input::end_of_data(name: string, source: string)
{
if ( name != "hosts" )
return;
# now all data is in the table
print "Hosts list has been successfully imported";
# List the users of one host.
print hostslist[192.168.17.1]$users;
}

View file

@ -1,40 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
sumstats-countconns.bro
@load base/frameworks/sumstats
event connection_established(c: connection)
{
# Make an observation!
# This observation is global so the key is empty.
# Each established connection counts as one so the observation is always 1.
SumStats::observe("conn established",
SumStats::Key(),
SumStats::Observation($num=1));
}
event bro_init()
{
# Create the reducer.
# The reducer attaches to the "conn established" observation stream
# and uses the summing calculation on the observations.
local r1 = SumStats::Reducer($stream="conn established",
$apply=set(SumStats::SUM));
# Create the final sumstat.
# We give it an arbitrary name and make it collect data every minute.
# The reducer is then attached and a $epoch_result callback is given
# to finally do something with the data collected.
SumStats::create([$name = "counting connections",
$epoch = 1min,
$reducers = set(r1),
$epoch_result(ts: time, key: SumStats::Key, result: SumStats::Result) =
{
# This is the body of the callback that is called when a single
# result has been collected. We are just printing the total number
# of connections that were seen. The $sum field is provided as a
# double type value so we need to use %f as the format specifier.
print fmt("Number of connections established: %.0f", result["conn established"]$sum);
}]);
}

View file

@ -1,49 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
sumstats-toy-scan.bro
@load base/frameworks/sumstats
# We use the connection_attempt event to limit our observations to those
# which were attempted and not successful.
event connection_attempt(c: connection)
{
# Make an observation!
# This observation is about the host attempting the connection.
# Each established connection counts as one so the observation is always 1.
SumStats::observe("conn attempted",
SumStats::Key($host=c$id$orig_h),
SumStats::Observation($num=1));
}
event bro_init()
{
# Create the reducer.
# The reducer attaches to the "conn attempted" observation stream
# and uses the summing calculation on the observations. Keep
# in mind that there will be one result per key (connection originator).
local r1 = SumStats::Reducer($stream="conn attempted",
$apply=set(SumStats::SUM));
# Create the final sumstat.
# This is slightly different from the last example since we're providing
# a callback to calculate a value to check against the threshold with
# $threshold_val. The actual threshold itself is provided with $threshold.
# Another callback is provided for when a key crosses the threshold.
SumStats::create([$name = "finding scanners",
$epoch = 5min,
$reducers = set(r1),
# Provide a threshold.
$threshold = 5.0,
# Provide a callback to calculate a value from the result
# to check against the threshold field.
$threshold_val(key: SumStats::Key, result: SumStats::Result) =
{
return result["conn attempted"]$sum;
},
# Provide a callback for when a key crosses the threshold.
$threshold_crossed(key: SumStats::Key, result: SumStats::Result) =
{
print fmt("%s attempted %.0f or more connections", key$host, result["conn attempted"]$sum);
}]);
}

View file

@ -1,28 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
file_extraction.bro
global mime_to_ext: table[string] of string = {
["application/x-dosexec"] = "exe",
["text/plain"] = "txt",
["image/jpeg"] = "jpg",
["image/png"] = "png",
["text/html"] = "html",
};
event file_sniff(f: fa_file, meta: fa_metadata)
{
if ( f$source != "HTTP" )
return;
if ( ! meta?$mime_type )
return;
if ( meta$mime_type !in mime_to_ext )
return;
local fname = fmt("%s-%s.%s", f$source, f$id, mime_to_ext[meta$mime_type]);
print fmt("Extracting file %s", fname);
Files::add_analyzer(f, Files::ANALYZER_EXTRACT, [$extract_filename=fname]);
}

View file

@ -1,9 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
http_proxy_01.bro
event http_reply(c: connection, version: string, code: count, reason: string)
{
if ( /^[hH][tT][tT][pP]:/ in c$http$uri && c$http$status_code == 200 )
print fmt("A local server is acting as an open proxy: %s", c$id$resp_h);
}

View file

@ -1,30 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
http_proxy_02.bro
module HTTP;
export {
global success_status_codes: set[count] = {
200,
201,
202,
203,
204,
205,
206,
207,
208,
226,
304
};
}
event http_reply(c: connection, version: string, code: count, reason: string)
{
if ( /^[hH][tT][tT][pP]:/ in c$http$uri &&
c$http$status_code in HTTP::success_status_codes )
print fmt("A local server is acting as an open proxy: %s", c$id$resp_h);
}

View file

@ -1,35 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
http_proxy_03.bro
@load base/utils/site
redef Site::local_nets += { 192.168.0.0/16 };
module HTTP;
export {
global success_status_codes: set[count] = {
200,
201,
202,
203,
204,
205,
206,
207,
208,
226,
304
};
}
event http_reply(c: connection, version: string, code: count, reason: string)
{
if ( Site::is_local_addr(c$id$resp_h) &&
/^[hH][tT][tT][pP]:/ in c$http$uri &&
c$http$status_code in HTTP::success_status_codes )
print fmt("A local server is acting as an open proxy: %s", c$id$resp_h);
}

View file

@ -1,44 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
http_proxy_04.bro
@load base/utils/site
@load base/frameworks/notice
redef Site::local_nets += { 192.168.0.0/16 };
module HTTP;
export {
redef enum Notice::Type += {
Open_Proxy
};
global success_status_codes: set[count] = {
200,
201,
202,
203,
204,
205,
206,
207,
208,
226,
304
};
}
event http_reply(c: connection, version: string, code: count, reason: string)
{
if ( Site::is_local_addr(c$id$resp_h) &&
/^[hH][tT][tT][pP]:/ in c$http$uri &&
c$http$status_code in HTTP::success_status_codes )
NOTICE([$note=HTTP::Open_Proxy,
$msg=fmt("A local server is acting as an open proxy: %s",
c$id$resp_h),
$conn=c,
$identifier=cat(c$id$resp_h),
$suppress_for=1day]);
}

View file

@ -1,39 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
mimestats.bro
module MimeMetrics;
export {
redef enum Log::ID += { LOG };
type Info: record {
## Timestamp when the log line was finished and written.
ts: time &log;
## Time interval that the log line covers.
ts_delta: interval &log;
## The mime type
mtype: string &log;
## The number of unique local hosts that fetched this mime type
uniq_hosts: count &log;
## The number of hits to the mime type
hits: count &log;
## The total number of bytes received by this mime type
bytes: count &log;
};
## The frequency of logging the stats collected by this script.
const break_interval = 5mins &redef;
}
event HTTP::log_http(rec: HTTP::Info)
{
if ( Site::is_local_addr(rec$id$orig_h) && rec?$resp_mime_types )
{
local mime_type = rec$resp_mime_types[0];
SumStats::observe("mime.bytes", [$str=mime_type],
[$num=rec$response_body_len]);
SumStats::observe("mime.hits", [$str=mime_type],
[$str=cat(rec$id$orig_h)]);
}
}

View file

@ -1,8 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
mimestats.bro
local r1: SumStats::Reducer = [$stream="mime.bytes",
$apply=set(SumStats::SUM)];
local r2: SumStats::Reducer = [$stream="mime.hits",
$apply=set(SumStats::UNIQUE)];

View file

@ -1,18 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
mimestats.bro
SumStats::create([$name="mime-metrics",
$epoch=break_interval,
$reducers=set(r1, r2),
$epoch_result(ts: time, key: SumStats::Key, result: SumStats::Result) =
{
local l: Info;
l$ts = network_time();
l$ts_delta = break_interval;
l$mtype = key$str;
l$bytes = double_to_count(floor(result["mime.bytes"]$sum));
l$hits = result["mime.hits"]$num;
l$uniq_hosts = result["mime.hits"]$unique;
Log::write(MimeMetrics::LOG, l);
}]);

View file

@ -1,68 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
mimestats.bro
@load base/utils/site
@load base/frameworks/sumstats
redef Site::local_nets += { 10.0.0.0/8 };
module MimeMetrics;
export {
redef enum Log::ID += { LOG };
type Info: record {
## Timestamp when the log line was finished and written.
ts: time &log;
## Time interval that the log line covers.
ts_delta: interval &log;
## The mime type
mtype: string &log;
## The number of unique local hosts that fetched this mime type
uniq_hosts: count &log;
## The number of hits to the mime type
hits: count &log;
## The total number of bytes received by this mime type
bytes: count &log;
};
## The frequency of logging the stats collected by this script.
const break_interval = 5mins &redef;
}
event bro_init() &priority=3
{
Log::create_stream(MimeMetrics::LOG, [$columns=Info, $path="mime_metrics"]);
local r1: SumStats::Reducer = [$stream="mime.bytes",
$apply=set(SumStats::SUM)];
local r2: SumStats::Reducer = [$stream="mime.hits",
$apply=set(SumStats::UNIQUE)];
SumStats::create([$name="mime-metrics",
$epoch=break_interval,
$reducers=set(r1, r2),
$epoch_result(ts: time, key: SumStats::Key, result: SumStats::Result) =
{
local l: Info;
l$ts = network_time();
l$ts_delta = break_interval;
l$mtype = key$str;
l$bytes = double_to_count(floor(result["mime.bytes"]$sum));
l$hits = result["mime.hits"]$num;
l$uniq_hosts = result["mime.hits"]$unique;
Log::write(MimeMetrics::LOG, l);
}]);
}
event HTTP::log_http(rec: HTTP::Info)
{
if ( Site::is_local_addr(rec$id$orig_h) && rec?$resp_mime_types )
{
local mime_type = rec$resp_mime_types[0];
SumStats::observe("mime.bytes", [$str=mime_type],
[$num=rec$response_body_len]);
SumStats::observe("mime.hits", [$str=mime_type],
[$str=cat(rec$id$orig_h)]);
}
}

View file

@ -1,28 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
conditional-notice.bro
@load protocols/ssl/expiring-certs
const watched_servers: set[addr] = {
87.98.220.10,
} &redef;
# Site::local_nets usually isn't something you need to modify if
# BroControl automatically sets it up from networks.cfg. It's
# shown here for completeness.
redef Site::local_nets += {
87.98.0.0/16,
};
hook Notice::policy(n: Notice::Info)
{
if ( n$note != SSL::Certificate_Expired )
return;
if ( n$id$resp_h !in watched_servers )
return;
add n$actions[Notice::ACTION_EMAIL];
}

View file

@ -1,10 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
connection_record_01.bro
@load base/protocols/conn
event connection_state_remove(c: connection)
{
print c;
}

View file

@ -1,11 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
connection_record_02.bro
@load base/protocols/conn
@load base/protocols/http
event connection_state_remove(c: connection)
{
print c;
}

View file

@ -1,26 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_record_01.bro
type Service: record {
name: string;
ports: set[port];
rfc: count;
};
function print_service(serv: Service)
{
print fmt("Service: %s(RFC%d)",serv$name, serv$rfc);
for ( p in serv$ports )
print fmt(" port: %s", p);
}
event bro_init()
{
local dns: Service = [$name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
local http: Service = [$name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
print_service(dns);
print_service(http);
}

View file

@ -1,45 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_record_02.bro
type Service: record {
name: string;
ports: set[port];
rfc: count;
};
type System: record {
name: string;
services: set[Service];
};
function print_service(serv: Service)
{
print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc);
for ( p in serv$ports )
print fmt(" port: %s", p);
}
function print_system(sys: System)
{
print fmt("System: %s", sys$name);
for ( s in sys$services )
print_service(s);
}
event bro_init()
{
local server01: System;
server01$name = "morlock";
add server01$services[[ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035]];
add server01$services[[ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616]];
print_system(server01);
# local dns: Service = [ $name="dns", $ports=set(53/udp, 53/tcp), $rfc=1035];
# local http: Service = [ $name="http", $ports=set(80/tcp, 8080/tcp), $rfc=2616];
# print_service(dns);
# print_service(http);
}

View file

@ -1,9 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_set_declaration.bro
event bro_init()
{
local ssl_ports: set[port];
local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
}

View file

@ -1,9 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_set_declaration.bro
for ( i in ssl_ports )
print fmt("SSL Port: %s", i);
for ( i in non_ssl_ports )
print fmt("Non-SSL Port: %s", i);

View file

@ -1,7 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_set_declaration.bro
# Check for SMTPS
if ( 587/tcp !in ssl_ports )
add ssl_ports[587/tcp];

View file

@ -1,26 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_set_declaration.bro
event bro_init()
{
local ssl_ports: set[port];
local non_ssl_ports = set( 23/tcp, 80/tcp, 143/tcp, 25/tcp );
# SSH
add ssl_ports[22/tcp];
# HTTPS
add ssl_ports[443/tcp];
# IMAPS
add ssl_ports[993/tcp];
# Check for SMTPS
if ( 587/tcp !in ssl_ports )
add ssl_ports[587/tcp];
for ( i in ssl_ports )
print fmt("SSL Port: %s", i);
for ( i in non_ssl_ports )
print fmt("Non-SSL Port: %s", i);
}

View file

@ -1,17 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_table_complex.bro
event bro_init()
{
local samurai_flicks: table[string, string, count, string] of string;
samurai_flicks["Kihachi Okamoto", "Toho", 1968, "Tatsuya Nakadai"] = "Kiru";
samurai_flicks["Hideo Gosha", "Fuji", 1969, "Tatsuya Nakadai"] = "Goyokin";
samurai_flicks["Masaki Kobayashi", "Shochiku Eiga", 1962, "Tatsuya Nakadai" ] = "Harakiri";
samurai_flicks["Yoji Yamada", "Eisei Gekijo", 2002, "Hiroyuki Sanada" ] = "Tasogare Seibei";
for ( [d, s, y, a] in samurai_flicks )
print fmt("%s was released in %d by %s studios, directed by %s and starring %s", samurai_flicks[d, s, y, a], y, s, d, a);
}

View file

@ -1,23 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_table_declaration.bro
event bro_init()
{
# Declaration of the table.
local ssl_services: table[string] of port;
# Initialize the table.
ssl_services = table(["SSH"] = 22/tcp, ["HTTPS"] = 443/tcp);
# Insert one key-yield pair into the table.
ssl_services["IMAPS"] = 993/tcp;
# Check if the key "SMTPS" is not in the table.
if ( "SMTPS" !in ssl_services )
ssl_services["SMTPS"] = 587/tcp;
# Iterate over each key in the table.
for ( k in ssl_services )
print fmt("Service Name: %s - Common Port: %s", k, ssl_services[k]);
}

View file

@ -1,19 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_vector_declaration.bro
event bro_init()
{
local v1: vector of count;
local v2 = vector(1, 2, 3, 4);
v1 += 1;
v1 += 2;
v1 += 3;
v1 += 4;
print fmt("contents of v1: %s", v1);
print fmt("length of v1: %d", |v1|);
print fmt("contents of v2: %s", v2);
print fmt("length of v2: %d", |v2|);
}

View file

@ -1,11 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_struct_vector_iter.bro
event bro_init()
{
local addr_vector: vector of addr = vector(1.2.3.4, 2.3.4.5, 3.4.5.6);
for (i in addr_vector)
print mask_addr(addr_vector[i], 18);
}

View file

@ -1,13 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_const.bro
const port_list: table[port] of string &redef;
redef port_list += { [6666/tcp] = "IRC"};
redef port_list += { [80/tcp] = "WWW" };
event bro_init()
{
print port_list;
}

View file

@ -1,8 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_const_simple.bro
@load base/protocols/http
redef HTTP::default_capture_password = T;

View file

@ -1,13 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_declaration.bro
event bro_init()
{
local a: int;
a = 10;
local b = 10;
if ( a == b )
print fmt("A: %d, B: %d", a, b);
}

View file

@ -1,22 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_interval.bro
# Store the time the previous connection was established.
global last_connection_time: time;
# boolean value to indicate whether we have seen a previous connection.
global connection_seen: bool = F;
event connection_established(c: connection)
{
local net_time: time = network_time();
print fmt("%s: New connection established from %s to %s", strftime("%Y/%M/%d %H:%m:%S", net_time), c$id$orig_h, c$id$resp_h);
if ( connection_seen )
print fmt(" Time since last connection: %s", net_time - last_connection_time);
last_connection_time = net_time;
connection_seen = T;
}

View file

@ -1,15 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_local.bro
function add_two(i: count): count
{
local added_two = i+2;
print fmt("i + 2 = %d", added_two);
return added_two;
}
event bro_init()
{
local test = add_two(10);
}

View file

@ -1,17 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_pattern_01.bro
event bro_init()
{
local test_string = "The quick brown fox jumps over the lazy dog.";
local test_pattern = /quick|lazy/;
if ( test_pattern in test_string )
{
local results = split(test_string, test_pattern);
print results[1];
print results[2];
print results[3];
}
}

View file

@ -1,14 +0,0 @@
# @TEST-EXEC: cat %INPUT >output && btest-diff output
data_type_pattern_02.bro
event bro_init()
{
local test_string = "equality";
local test_pattern = /equal/;
print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
test_pattern = /equality/;
print fmt("%s and %s %s equal", test_string, test_pattern, test_pattern == test_string ? "are" : "are not");
}

Some files were not shown because too many files have changed in this diff Show more