mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/vladg/kerberos
This commit is contained in:
commit
1ff45c9fe1
547 changed files with 20267 additions and 4059 deletions
|
@ -2,3 +2,4 @@
|
|||
@load ./contents
|
||||
@load ./inactivity
|
||||
@load ./polling
|
||||
@load ./thresholds
|
||||
|
|
|
@ -62,6 +62,12 @@ export {
|
|||
## field will be left empty at all times.
|
||||
local_orig: bool &log &optional;
|
||||
|
||||
## If the connection is responded to locally, this value will be T.
|
||||
## If it was responded to remotely it will be F. In the case that
|
||||
## the :bro:id:`Site::local_nets` variable is undefined, this
|
||||
## field will be left empty at all times.
|
||||
local_resp: bool &log &optional;
|
||||
|
||||
## Indicates the number of bytes missed in content gaps, which
|
||||
## is representative of packet loss. A value other than zero
|
||||
## will normally cause protocol analysis to fail but some
|
||||
|
@ -121,7 +127,7 @@ redef record connection += {
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn]);
|
||||
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn, $path="conn"]);
|
||||
}
|
||||
|
||||
function conn_state(c: connection, trans: transport_proto): string
|
||||
|
@ -201,7 +207,10 @@ function set_conn(c: connection, eoc: bool)
|
|||
add c$conn$tunnel_parents[c$tunnel[|c$tunnel|-1]$uid];
|
||||
c$conn$proto=get_port_transport_proto(c$id$resp_p);
|
||||
if( |Site::local_nets| > 0 )
|
||||
{
|
||||
c$conn$local_orig=Site::is_local_addr(c$id$orig_h);
|
||||
c$conn$local_resp=Site::is_local_addr(c$id$resp_h);
|
||||
}
|
||||
|
||||
if ( eoc )
|
||||
{
|
||||
|
|
274
scripts/base/protocols/conn/thresholds.bro
Normal file
274
scripts/base/protocols/conn/thresholds.bro
Normal file
|
@ -0,0 +1,274 @@
|
|||
##! Implements a generic API to throw events when a connection crosses a
|
||||
##! fixed threshold of bytes or packets.
|
||||
|
||||
module ConnThreshold;
|
||||
|
||||
export {
|
||||
|
||||
type Thresholds: record {
|
||||
orig_byte: set[count] &default=count_set(); ##< current originator byte thresholds we watch for
|
||||
resp_byte: set[count] &default=count_set(); ##< current responder byte thresholds we watch for
|
||||
orig_packet: set[count] &default=count_set(); ##< corrent originator packet thresholds we watch for
|
||||
resp_packet: set[count] &default=count_set(); ##< corrent responder packet thresholds we watch for
|
||||
};
|
||||
|
||||
## Sets a byte threshold for connection sizes, adding it to potentially already existing thresholds.
|
||||
## conn_bytes_threshold_crossed will be raised for each set threshold.
|
||||
##
|
||||
## cid: The connection id.
|
||||
##
|
||||
## threshold: Threshold in bytes.
|
||||
##
|
||||
## is_orig: If true, threshold is set for bytes from originator, otherwise for bytes from responder.
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
##
|
||||
## .. bro:see:: bytes_threshold_crossed packets_threshold_crossed set_packets_threshold
|
||||
## delete_bytes_threshold delete_packets_threshold
|
||||
global set_bytes_threshold: function(c: connection, threshold: count, is_orig: bool): bool;
|
||||
|
||||
## Sets a packet threshold for connection sizes, adding it to potentially already existing thresholds.
|
||||
## conn_packets_threshold_crossed will be raised for each set threshold.
|
||||
##
|
||||
## cid: The connection id.
|
||||
##
|
||||
## threshold: Threshold in packets.
|
||||
##
|
||||
## is_orig: If true, threshold is set for packets from originator, otherwise for packets from responder.
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
##
|
||||
## .. bro:see:: bytes_threshold_crossed packets_threshold_crossed set_bytes_threshold
|
||||
## delete_bytes_threshold delete_packets_threshold
|
||||
global set_packets_threshold: function(c: connection, threshold: count, is_orig: bool): bool;
|
||||
|
||||
## Deletes a byte threshold for connection sizes.
|
||||
##
|
||||
## cid: The connection id.
|
||||
##
|
||||
## threshold: Threshold in bytes to remove.
|
||||
##
|
||||
## is_orig: If true, threshold is removed for packets from originator, otherwhise for packets from responder.
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
##
|
||||
## .. bro:see:: bytes_threshold_crossed packets_threshold_crossed set_bytes_threshold set_packets_threshold
|
||||
## delete_packets_threshold
|
||||
global delete_bytes_threshold: function(c: connection, threshold: count, is_orig: bool): bool;
|
||||
|
||||
## Deletes a packet threshold for connection sizes.
|
||||
##
|
||||
## cid: The connection id.
|
||||
##
|
||||
## threshold: Threshold in packets.
|
||||
##
|
||||
## is_orig: If true, threshold is removed for packets from originator, otherwise for packets from responder.
|
||||
##
|
||||
## Returns: T on success, F on failure.
|
||||
##
|
||||
## .. bro:see:: bytes_threshold_crossed packets_threshold_crossed set_bytes_threshold set_packets_threshold
|
||||
## delete_bytes_threshold
|
||||
global delete_packets_threshold: function(c: connection, threshold: count, is_orig: bool): bool;
|
||||
|
||||
## Generated for a connection that crossed a set byte threshold
|
||||
##
|
||||
## c: the connection
|
||||
##
|
||||
## threshold: the threshold that was set
|
||||
##
|
||||
## is_orig: True if the threshold was crossed by the originator of the connection
|
||||
##
|
||||
## .. bro:see:: packets_threshold_crossed set_bytes_threshold set_packets_threshold
|
||||
## delete_bytes_threshold delete_packets_threshold
|
||||
global bytes_threshold_crossed: event(c: connection, threshold: count, is_orig: bool);
|
||||
|
||||
## Generated for a connection that crossed a set byte threshold
|
||||
##
|
||||
## c: the connection
|
||||
##
|
||||
## threshold: the threshold that was set
|
||||
##
|
||||
## is_orig: True if the threshold was crossed by the originator of the connection
|
||||
##
|
||||
## .. bro:see:: bytes_threshold_crossed set_bytes_threshold set_packets_threshold
|
||||
## delete_bytes_threshold delete_packets_threshold
|
||||
global packets_threshold_crossed: event(c: connection, threshold: count, is_orig: bool);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
thresholds: ConnThreshold::Thresholds &optional;
|
||||
};
|
||||
|
||||
function set_conn(c: connection)
|
||||
{
|
||||
if ( c?$thresholds )
|
||||
return;
|
||||
|
||||
c$thresholds = Thresholds();
|
||||
}
|
||||
|
||||
function find_min_threshold(t: set[count]): count
|
||||
{
|
||||
if ( |t| == 0 )
|
||||
return 0;
|
||||
|
||||
local first = T;
|
||||
local min: count = 0;
|
||||
|
||||
for ( i in t )
|
||||
{
|
||||
if ( first )
|
||||
{
|
||||
min = i;
|
||||
first = F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( i < min )
|
||||
min = i;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
function set_current_threshold(c: connection, bytes: bool, is_orig: bool): bool
|
||||
{
|
||||
local t: count = 0;
|
||||
local cur: count = 0;
|
||||
|
||||
if ( bytes && is_orig )
|
||||
{
|
||||
t = find_min_threshold(c$thresholds$orig_byte);
|
||||
cur = get_current_conn_bytes_threshold(c$id, is_orig);
|
||||
}
|
||||
else if ( bytes && ! is_orig )
|
||||
{
|
||||
t = find_min_threshold(c$thresholds$resp_byte);
|
||||
cur = get_current_conn_bytes_threshold(c$id, is_orig);
|
||||
}
|
||||
else if ( ! bytes && is_orig )
|
||||
{
|
||||
t = find_min_threshold(c$thresholds$orig_packet);
|
||||
cur = get_current_conn_packets_threshold(c$id, is_orig);
|
||||
}
|
||||
else if ( ! bytes && ! is_orig )
|
||||
{
|
||||
t = find_min_threshold(c$thresholds$resp_packet);
|
||||
cur = get_current_conn_packets_threshold(c$id, is_orig);
|
||||
}
|
||||
|
||||
if ( t == cur )
|
||||
return T;
|
||||
|
||||
if ( bytes && is_orig )
|
||||
return set_current_conn_bytes_threshold(c$id, t, T);
|
||||
else if ( bytes && ! is_orig )
|
||||
return set_current_conn_bytes_threshold(c$id, t, F);
|
||||
else if ( ! bytes && is_orig )
|
||||
return set_current_conn_packets_threshold(c$id, t, T);
|
||||
else if ( ! bytes && ! is_orig )
|
||||
return set_current_conn_packets_threshold(c$id, t, F);
|
||||
}
|
||||
|
||||
function set_bytes_threshold(c: connection, threshold: count, is_orig: bool): bool
|
||||
{
|
||||
set_conn(c);
|
||||
|
||||
if ( threshold == 0 )
|
||||
return F;
|
||||
|
||||
if ( is_orig )
|
||||
add c$thresholds$orig_byte[threshold];
|
||||
else
|
||||
add c$thresholds$resp_byte[threshold];
|
||||
|
||||
return set_current_threshold(c, T, is_orig);
|
||||
}
|
||||
|
||||
function set_packets_threshold(c: connection, threshold: count, is_orig: bool): bool
|
||||
{
|
||||
set_conn(c);
|
||||
|
||||
if ( threshold == 0 )
|
||||
return F;
|
||||
|
||||
if ( is_orig )
|
||||
add c$thresholds$orig_packet[threshold];
|
||||
else
|
||||
add c$thresholds$resp_packet[threshold];
|
||||
|
||||
return set_current_threshold(c, F, is_orig);
|
||||
}
|
||||
|
||||
function delete_bytes_threshold(c: connection, threshold: count, is_orig: bool): bool
|
||||
{
|
||||
set_conn(c);
|
||||
|
||||
if ( is_orig && threshold in c$thresholds$orig_byte )
|
||||
{
|
||||
delete c$thresholds$orig_byte[threshold];
|
||||
set_current_threshold(c, T, is_orig);
|
||||
return T;
|
||||
}
|
||||
else if ( ! is_orig && threshold in c$thresholds$resp_byte )
|
||||
{
|
||||
delete c$thresholds$resp_byte[threshold];
|
||||
set_current_threshold(c, T, is_orig);
|
||||
return T;
|
||||
}
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
function delete_packets_threshold(c: connection, threshold: count, is_orig: bool): bool
|
||||
{
|
||||
set_conn(c);
|
||||
|
||||
if ( is_orig && threshold in c$thresholds$orig_packet )
|
||||
{
|
||||
delete c$thresholds$orig_packet[threshold];
|
||||
set_current_threshold(c, F, is_orig);
|
||||
return T;
|
||||
}
|
||||
else if ( ! is_orig && threshold in c$thresholds$resp_packet )
|
||||
{
|
||||
delete c$thresholds$resp_packet[threshold];
|
||||
set_current_threshold(c, F, is_orig);
|
||||
return T;
|
||||
}
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
event conn_bytes_threshold_crossed(c: connection, threshold: count, is_orig: bool) &priority=5
|
||||
{
|
||||
if ( is_orig && threshold in c$thresholds$orig_byte )
|
||||
{
|
||||
delete c$thresholds$orig_byte[threshold];
|
||||
event ConnThreshold::bytes_threshold_crossed(c, threshold, is_orig);
|
||||
}
|
||||
else if ( ! is_orig && threshold in c$thresholds$resp_byte )
|
||||
{
|
||||
delete c$thresholds$resp_byte[threshold];
|
||||
event ConnThreshold::bytes_threshold_crossed(c, threshold, is_orig);
|
||||
}
|
||||
|
||||
set_current_threshold(c, T, is_orig);
|
||||
}
|
||||
|
||||
event conn_packets_threshold_crossed(c: connection, threshold: count, is_orig: bool) &priority=5
|
||||
{
|
||||
if ( is_orig && threshold in c$thresholds$orig_packet )
|
||||
{
|
||||
delete c$thresholds$orig_packet[threshold];
|
||||
event ConnThreshold::packets_threshold_crossed(c, threshold, is_orig);
|
||||
}
|
||||
else if ( ! is_orig && threshold in c$thresholds$resp_packet )
|
||||
{
|
||||
delete c$thresholds$resp_packet[threshold];
|
||||
event ConnThreshold::packets_threshold_crossed(c, threshold, is_orig);
|
||||
}
|
||||
|
||||
set_current_threshold(c, F, is_orig);
|
||||
}
|
|
@ -49,7 +49,7 @@ redef likely_server_ports += { 67/udp };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp]);
|
||||
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp, $path="dhcp"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3]);
|
||||
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3, $path="dnp3"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3_TCP, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns]);
|
||||
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns, $path="dns"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, ports);
|
||||
}
|
||||
|
||||
|
@ -305,6 +305,9 @@ hook DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string)
|
|||
|
||||
if ( ans$answer_type == DNS_ANS )
|
||||
{
|
||||
if ( ! c$dns?$query )
|
||||
c$dns$query = ans$query;
|
||||
|
||||
c$dns$AA = msg$AA;
|
||||
c$dns$RA = msg$RA;
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
##! GridFTP data channels are identified by a heuristic that relies on
|
||||
##! the fact that default settings for GridFTP clients typically
|
||||
##! mutually authenticate the data channel with TLS/SSL and negotiate a
|
||||
##! NULL bulk cipher (no encryption). Connections with those
|
||||
##! attributes are then polled for two minutes with decreasing frequency
|
||||
##! to check if the transfer sizes are large enough to indicate a
|
||||
##! GridFTP data channel that would be undesirable to analyze further
|
||||
##! (e.g. stop TCP reassembly). A side effect is that true connection
|
||||
##! sizes are not logged, but at the benefit of saving CPU cycles that
|
||||
##! would otherwise go to analyzing the large (and likely benign) connections.
|
||||
##! NULL bulk cipher (no encryption). Connections with those attributes
|
||||
##! are marked as GridFTP if the data transfer within the first two minutes
|
||||
##! is big enough to indicate a GripFTP data channel that would be
|
||||
##! undesirable to analyze further (e.g. stop TCP reassembly). A side
|
||||
##! effect is that true connection sizes are not logged, but at the benefit
|
||||
##! of saving CPU cycles that would otherwise go to analyzing the large
|
||||
##! (and likely benign) connections.
|
||||
|
||||
@load ./info
|
||||
@load ./main
|
||||
|
@ -32,23 +32,14 @@ export {
|
|||
## GridFTP data channel.
|
||||
const size_threshold = 1073741824 &redef;
|
||||
|
||||
## Max number of times to check whether a connection's size exceeds the
|
||||
## Time during which we check whether a connection's size exceeds the
|
||||
## :bro:see:`GridFTP::size_threshold`.
|
||||
const max_poll_count = 15 &redef;
|
||||
const max_time = 2 min &redef;
|
||||
|
||||
## Whether to skip further processing of the GridFTP data channel once
|
||||
## detected, which may help performance.
|
||||
const skip_data = T &redef;
|
||||
|
||||
## Base amount of time between checking whether a GridFTP data connection
|
||||
## has transferred more than :bro:see:`GridFTP::size_threshold` bytes.
|
||||
const poll_interval = 1sec &redef;
|
||||
|
||||
## The amount of time the base :bro:see:`GridFTP::poll_interval` is
|
||||
## increased by each poll interval. Can be used to make more frequent
|
||||
## checks at the start of a connection and gradually slow down.
|
||||
const poll_interval_increase = 1sec &redef;
|
||||
|
||||
## Raised when a GridFTP data channel is detected.
|
||||
##
|
||||
## c: The connection pertaining to the GridFTP data channel.
|
||||
|
@ -79,23 +70,27 @@ event ftp_request(c: connection, command: string, arg: string) &priority=4
|
|||
c$ftp$last_auth_requested = arg;
|
||||
}
|
||||
|
||||
function size_callback(c: connection, cnt: count): interval
|
||||
event ConnThreshold::bytes_threshold_crossed(c: connection, threshold: count, is_orig: bool)
|
||||
{
|
||||
if ( c$orig$size > size_threshold || c$resp$size > size_threshold )
|
||||
if ( threshold < size_threshold || "gridftp-data" in c$service || c$duration > max_time )
|
||||
return;
|
||||
|
||||
add c$service["gridftp-data"];
|
||||
event GridFTP::data_channel_detected(c);
|
||||
|
||||
if ( skip_data )
|
||||
skip_further_processing(c$id);
|
||||
}
|
||||
|
||||
event gridftp_possibility_timeout(c: connection)
|
||||
{
|
||||
# only remove if we did not already detect it and the connection
|
||||
# is not yet at its end.
|
||||
if ( "gridftp-data" !in c$service && ! c$conn?$service )
|
||||
{
|
||||
add c$service["gridftp-data"];
|
||||
event GridFTP::data_channel_detected(c);
|
||||
|
||||
if ( skip_data )
|
||||
skip_further_processing(c$id);
|
||||
|
||||
return -1sec;
|
||||
ConnThreshold::delete_bytes_threshold(c, size_threshold, T);
|
||||
ConnThreshold::delete_bytes_threshold(c, size_threshold, F);
|
||||
}
|
||||
|
||||
if ( cnt >= max_poll_count )
|
||||
return -1sec;
|
||||
|
||||
return poll_interval + poll_interval_increase * cnt;
|
||||
}
|
||||
|
||||
event ssl_established(c: connection) &priority=5
|
||||
|
@ -118,5 +113,9 @@ event ssl_established(c: connection) &priority=-3
|
|||
# By default GridFTP data channels do mutual authentication and
|
||||
# negotiate a cipher suite with a NULL bulk cipher.
|
||||
if ( data_channel_initial_criteria(c) )
|
||||
ConnPolling::watch(c, size_callback, 0, 0secs);
|
||||
{
|
||||
ConnThreshold::set_bytes_threshold(c, size_threshold, T);
|
||||
ConnThreshold::set_bytes_threshold(c, size_threshold, F);
|
||||
schedule max_time { gridftp_possibility_timeout(c) };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp]);
|
||||
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp, $path="ftp"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_FTP, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ redef likely_server_ports += { ports };
|
|||
# Initialize the HTTP logging stream and ports.
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http]);
|
||||
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http, $path="http"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log]);
|
||||
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log, $path="irc"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_IRC, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus]);
|
||||
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus, $path="modbus"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_MODBUS, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ const ports = { 1434/tcp, 3306/tcp };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql]);
|
||||
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql, $path="mysql"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_MYSQL, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ const ports = { 1812/udp };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius]);
|
||||
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius, $path="radius"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
|
||||
}
|
||||
|
||||
|
|
3
scripts/base/protocols/rdp/__load__.bro
Normal file
3
scripts/base/protocols/rdp/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
|||
@load ./consts
|
||||
@load ./main
|
||||
@load-sigs ./dpd.sig
|
323
scripts/base/protocols/rdp/consts.bro
Normal file
323
scripts/base/protocols/rdp/consts.bro
Normal file
|
@ -0,0 +1,323 @@
|
|||
module RDP;
|
||||
|
||||
export {
|
||||
# http://www.c-amie.co.uk/technical/mstsc-versions/
|
||||
const builds = {
|
||||
[0419] = "RDP 4.0",
|
||||
[2195] = "RDP 5.0",
|
||||
[2221] = "RDP 5.0",
|
||||
[2600] = "RDP 5.1",
|
||||
[3790] = "RDP 5.2",
|
||||
[6000] = "RDP 6.0",
|
||||
[6001] = "RDP 6.1",
|
||||
[6002] = "RDP 6.2",
|
||||
[7600] = "RDP 7.0",
|
||||
[7601] = "RDP 7.1",
|
||||
[9200] = "RDP 8.0",
|
||||
[9600] = "RDP 8.1",
|
||||
[25189] = "RDP 8.0 (Mac)",
|
||||
[25282] = "RDP 8.0 (Mac)"
|
||||
} &default = function(n: count): string { return fmt("client_build-%d", n); };
|
||||
|
||||
const security_protocols = {
|
||||
[0x00] = "RDP",
|
||||
[0x01] = "SSL",
|
||||
[0x02] = "HYBRID",
|
||||
[0x08] = "HYBRID_EX"
|
||||
} &default = function(n: count): string { return fmt("security_protocol-%d", n); };
|
||||
|
||||
const failure_codes = {
|
||||
[0x01] = "SSL_REQUIRED_BY_SERVER",
|
||||
[0x02] = "SSL_NOT_ALLOWED_BY_SERVER",
|
||||
[0x03] = "SSL_CERT_NOT_ON_SERVER",
|
||||
[0x04] = "INCONSISTENT_FLAGS",
|
||||
[0x05] = "HYBRID_REQUIRED_BY_SERVER",
|
||||
[0x06] = "SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER"
|
||||
} &default = function(n: count): string { return fmt("failure_code-%d", n); };
|
||||
|
||||
const cert_types = {
|
||||
[1] = "RSA",
|
||||
[2] = "X.509"
|
||||
} &default = function(n: count): string { return fmt("cert_type-%d", n); };
|
||||
|
||||
const encryption_methods = {
|
||||
[0] = "None",
|
||||
[1] = "40bit",
|
||||
[2] = "128bit",
|
||||
[8] = "56bit",
|
||||
[10] = "FIPS"
|
||||
} &default = function(n: count): string { return fmt("encryption_method-%d", n); };
|
||||
|
||||
const encryption_levels = {
|
||||
[0] = "None",
|
||||
[1] = "Low",
|
||||
[2] = "Client compatible",
|
||||
[3] = "High",
|
||||
[4] = "FIPS"
|
||||
} &default = function(n: count): string { return fmt("encryption_level-%d", n); };
|
||||
|
||||
const high_color_depths = {
|
||||
[0x0004] = "4bit",
|
||||
[0x0008] = "8bit",
|
||||
[0x000F] = "15bit",
|
||||
[0x0010] = "16bit",
|
||||
[0x0018] = "24bit"
|
||||
} &default = function(n: count): string { return fmt("high_color_depth-%d", n); };
|
||||
|
||||
const color_depths = {
|
||||
[0x0001] = "24bit",
|
||||
[0x0002] = "16bit",
|
||||
[0x0004] = "15bit",
|
||||
[0x0008] = "32bit"
|
||||
} &default = function(n: count): string { return fmt("color_depth-%d", n); };
|
||||
|
||||
const results = {
|
||||
[0] = "Success",
|
||||
[1] = "User rejected",
|
||||
[2] = "Resources not available",
|
||||
[3] = "Rejected for symmetry breaking",
|
||||
[4] = "Locked conference",
|
||||
} &default = function(n: count): string { return fmt("result-%d", n); };
|
||||
|
||||
# http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
|
||||
const languages = {
|
||||
[1078] = "Afrikaans - South Africa",
|
||||
[1052] = "Albanian - Albania",
|
||||
[1156] = "Alsatian",
|
||||
[1118] = "Amharic - Ethiopia",
|
||||
[1025] = "Arabic - Saudi Arabia",
|
||||
[5121] = "Arabic - Algeria",
|
||||
[15361] = "Arabic - Bahrain",
|
||||
[3073] = "Arabic - Egypt",
|
||||
[2049] = "Arabic - Iraq",
|
||||
[11265] = "Arabic - Jordan",
|
||||
[13313] = "Arabic - Kuwait",
|
||||
[12289] = "Arabic - Lebanon",
|
||||
[4097] = "Arabic - Libya",
|
||||
[6145] = "Arabic - Morocco",
|
||||
[8193] = "Arabic - Oman",
|
||||
[16385] = "Arabic - Qatar",
|
||||
[10241] = "Arabic - Syria",
|
||||
[7169] = "Arabic - Tunisia",
|
||||
[14337] = "Arabic - U.A.E.",
|
||||
[9217] = "Arabic - Yemen",
|
||||
[1067] = "Armenian - Armenia",
|
||||
[1101] = "Assamese",
|
||||
[2092] = "Azeri (Cyrillic)",
|
||||
[1068] = "Azeri (Latin)",
|
||||
[1133] = "Bashkir",
|
||||
[1069] = "Basque",
|
||||
[1059] = "Belarusian",
|
||||
[1093] = "Bengali (India)",
|
||||
[2117] = "Bengali (Bangladesh)",
|
||||
[5146] = "Bosnian (Bosnia/Herzegovina)",
|
||||
[1150] = "Breton",
|
||||
[1026] = "Bulgarian",
|
||||
[1109] = "Burmese",
|
||||
[1027] = "Catalan",
|
||||
[1116] = "Cherokee - United States",
|
||||
[2052] = "Chinese - People's Republic of China",
|
||||
[4100] = "Chinese - Singapore",
|
||||
[1028] = "Chinese - Taiwan",
|
||||
[3076] = "Chinese - Hong Kong SAR",
|
||||
[5124] = "Chinese - Macao SAR",
|
||||
[1155] = "Corsican",
|
||||
[1050] = "Croatian",
|
||||
[4122] = "Croatian (Bosnia/Herzegovina)",
|
||||
[1029] = "Czech",
|
||||
[1030] = "Danish",
|
||||
[1164] = "Dari",
|
||||
[1125] = "Divehi",
|
||||
[1043] = "Dutch - Netherlands",
|
||||
[2067] = "Dutch - Belgium",
|
||||
[1126] = "Edo",
|
||||
[1033] = "English - United States",
|
||||
[2057] = "English - United Kingdom",
|
||||
[3081] = "English - Australia",
|
||||
[10249] = "English - Belize",
|
||||
[4105] = "English - Canada",
|
||||
[9225] = "English - Caribbean",
|
||||
[15369] = "English - Hong Kong SAR",
|
||||
[16393] = "English - India",
|
||||
[14345] = "English - Indonesia",
|
||||
[6153] = "English - Ireland",
|
||||
[8201] = "English - Jamaica",
|
||||
[17417] = "English - Malaysia",
|
||||
[5129] = "English - New Zealand",
|
||||
[13321] = "English - Philippines",
|
||||
[18441] = "English - Singapore",
|
||||
[7177] = "English - South Africa",
|
||||
[11273] = "English - Trinidad",
|
||||
[12297] = "English - Zimbabwe",
|
||||
[1061] = "Estonian",
|
||||
[1080] = "Faroese",
|
||||
[1065] = "Farsi",
|
||||
[1124] = "Filipino",
|
||||
[1035] = "Finnish",
|
||||
[1036] = "French - France",
|
||||
[2060] = "French - Belgium",
|
||||
[11276] = "French - Cameroon",
|
||||
[3084] = "French - Canada",
|
||||
[9228] = "French - Democratic Rep. of Congo",
|
||||
[12300] = "French - Cote d'Ivoire",
|
||||
[15372] = "French - Haiti",
|
||||
[5132] = "French - Luxembourg",
|
||||
[13324] = "French - Mali",
|
||||
[6156] = "French - Monaco",
|
||||
[14348] = "French - Morocco",
|
||||
[58380] = "French - North Africa",
|
||||
[8204] = "French - Reunion",
|
||||
[10252] = "French - Senegal",
|
||||
[4108] = "French - Switzerland",
|
||||
[7180] = "French - West Indies",
|
||||
[1122] = "French - West Indies",
|
||||
[1127] = "Fulfulde - Nigeria",
|
||||
[1071] = "FYRO Macedonian",
|
||||
[1110] = "Galician",
|
||||
[1079] = "Georgian",
|
||||
[1031] = "German - Germany",
|
||||
[3079] = "German - Austria",
|
||||
[5127] = "German - Liechtenstein",
|
||||
[4103] = "German - Luxembourg",
|
||||
[2055] = "German - Switzerland",
|
||||
[1032] = "Greek",
|
||||
[1135] = "Greenlandic",
|
||||
[1140] = "Guarani - Paraguay",
|
||||
[1095] = "Gujarati",
|
||||
[1128] = "Hausa - Nigeria",
|
||||
[1141] = "Hawaiian - United States",
|
||||
[1037] = "Hebrew",
|
||||
[1081] = "Hindi",
|
||||
[1038] = "Hungarian",
|
||||
[1129] = "Ibibio - Nigeria",
|
||||
[1039] = "Icelandic",
|
||||
[1136] = "Igbo - Nigeria",
|
||||
[1057] = "Indonesian",
|
||||
[1117] = "Inuktitut",
|
||||
[2108] = "Irish",
|
||||
[1040] = "Italian - Italy",
|
||||
[2064] = "Italian - Switzerland",
|
||||
[1041] = "Japanese",
|
||||
[1158] = "K'iche",
|
||||
[1099] = "Kannada",
|
||||
[1137] = "Kanuri - Nigeria",
|
||||
[2144] = "Kashmiri",
|
||||
[1120] = "Kashmiri (Arabic)",
|
||||
[1087] = "Kazakh",
|
||||
[1107] = "Khmer",
|
||||
[1159] = "Kinyarwanda",
|
||||
[1111] = "Konkani",
|
||||
[1042] = "Korean",
|
||||
[1088] = "Kyrgyz (Cyrillic)",
|
||||
[1108] = "Lao",
|
||||
[1142] = "Latin",
|
||||
[1062] = "Latvian",
|
||||
[1063] = "Lithuanian",
|
||||
[1134] = "Luxembourgish",
|
||||
[1086] = "Malay - Malaysia",
|
||||
[2110] = "Malay - Brunei Darussalam",
|
||||
[1100] = "Malayalam",
|
||||
[1082] = "Maltese",
|
||||
[1112] = "Manipuri",
|
||||
[1153] = "Maori - New Zealand",
|
||||
[1146] = "Mapudungun",
|
||||
[1102] = "Marathi",
|
||||
[1148] = "Mohawk",
|
||||
[1104] = "Mongolian (Cyrillic)",
|
||||
[2128] = "Mongolian (Mongolian)",
|
||||
[1121] = "Nepali",
|
||||
[2145] = "Nepali - India",
|
||||
[1044] = "Norwegian (Bokmål)",
|
||||
[2068] = "Norwegian (Nynorsk)",
|
||||
[1154] = "Occitan",
|
||||
[1096] = "Oriya",
|
||||
[1138] = "Oromo",
|
||||
[1145] = "Papiamentu",
|
||||
[1123] = "Pashto",
|
||||
[1045] = "Polish",
|
||||
[1046] = "Portuguese - Brazil",
|
||||
[2070] = "Portuguese - Portugal",
|
||||
[1094] = "Punjabi",
|
||||
[2118] = "Punjabi (Pakistan)",
|
||||
[1131] = "Quecha - Bolivia",
|
||||
[2155] = "Quecha - Ecuador",
|
||||
[3179] = "Quecha - Peru CB",
|
||||
[1047] = "Rhaeto-Romanic",
|
||||
[1048] = "Romanian",
|
||||
[2072] = "Romanian - Moldava",
|
||||
[1049] = "Russian",
|
||||
[2073] = "Russian - Moldava",
|
||||
[1083] = "Sami (Lappish)",
|
||||
[1103] = "Sanskrit",
|
||||
[1084] = "Scottish Gaelic",
|
||||
[1132] = "Sepedi",
|
||||
[3098] = "Serbian (Cyrillic)",
|
||||
[2074] = "Serbian (Latin)",
|
||||
[1113] = "Sindhi - India",
|
||||
[2137] = "Sindhi - Pakistan",
|
||||
[1115] = "Sinhalese - Sri Lanka",
|
||||
[1051] = "Slovak",
|
||||
[1060] = "Slovenian",
|
||||
[1143] = "Somali",
|
||||
[1070] = "Sorbian",
|
||||
[3082] = "Spanish - Spain (Modern Sort)",
|
||||
[1034] = "Spanish - Spain (Traditional Sort)",
|
||||
[11274] = "Spanish - Argentina",
|
||||
[16394] = "Spanish - Bolivia",
|
||||
[13322] = "Spanish - Chile",
|
||||
[9226] = "Spanish - Colombia",
|
||||
[5130] = "Spanish - Costa Rica",
|
||||
[7178] = "Spanish - Dominican Republic",
|
||||
[12298] = "Spanish - Ecuador",
|
||||
[17418] = "Spanish - El Salvador",
|
||||
[4106] = "Spanish - Guatemala",
|
||||
[18442] = "Spanish - Honduras",
|
||||
[22538] = "Spanish - Latin America",
|
||||
[2058] = "Spanish - Mexico",
|
||||
[19466] = "Spanish - Nicaragua",
|
||||
[6154] = "Spanish - Panama",
|
||||
[15370] = "Spanish - Paraguay",
|
||||
[10250] = "Spanish - Peru",
|
||||
[20490] = "Spanish - Puerto Rico",
|
||||
[21514] = "Spanish - United States",
|
||||
[14346] = "Spanish - Uruguay",
|
||||
[8202] = "Spanish - Venezuela",
|
||||
[1072] = "Sutu",
|
||||
[1089] = "Swahili",
|
||||
[1053] = "Swedish",
|
||||
[2077] = "Swedish - Finland",
|
||||
[1114] = "Syriac",
|
||||
[1064] = "Tajik",
|
||||
[1119] = "Tamazight (Arabic)",
|
||||
[2143] = "Tamazight (Latin)",
|
||||
[1097] = "Tamil",
|
||||
[1092] = "Tatar",
|
||||
[1098] = "Telugu",
|
||||
[1054] = "Thai",
|
||||
[2129] = "Tibetan - Bhutan",
|
||||
[1105] = "Tibetan - People's Republic of China",
|
||||
[2163] = "Tigrigna - Eritrea",
|
||||
[1139] = "Tigrigna - Ethiopia",
|
||||
[1073] = "Tsonga",
|
||||
[1074] = "Tswana",
|
||||
[1055] = "Turkish",
|
||||
[1090] = "Turkmen",
|
||||
[1152] = "Uighur - China",
|
||||
[1058] = "Ukrainian",
|
||||
[1056] = "Urdu",
|
||||
[2080] = "Urdu - India",
|
||||
[2115] = "Uzbek (Cyrillic)",
|
||||
[1091] = "Uzbek (Latin)",
|
||||
[1075] = "Venda",
|
||||
[1066] = "Vietnamese",
|
||||
[1106] = "Welsh",
|
||||
[1160] = "Wolof",
|
||||
[1076] = "Xhosa",
|
||||
[1157] = "Yakut",
|
||||
[1144] = "Yi",
|
||||
[1085] = "Yiddish",
|
||||
[1130] = "Yoruba",
|
||||
[1077] = "Zulu",
|
||||
[1279] = "HID (Human Interface Device)",
|
||||
} &default = function(n: count): string { return fmt("keyboard-%d", n); };
|
||||
}
|
12
scripts/base/protocols/rdp/dpd.sig
Normal file
12
scripts/base/protocols/rdp/dpd.sig
Normal file
|
@ -0,0 +1,12 @@
|
|||
signature dpd_rdp_client {
|
||||
ip-proto == tcp
|
||||
# Client request
|
||||
payload /.*(Cookie: mstshash\=|Duca.*(rdpdr|rdpsnd|drdynvc|cliprdr))/
|
||||
requires-reverse-signature dpd_rdp_server
|
||||
enable "rdp"
|
||||
}
|
||||
|
||||
signature dpd_rdp_server {
|
||||
ip-proto == tcp
|
||||
payload /(.{5}\xd0|.*McDn)/
|
||||
}
|
269
scripts/base/protocols/rdp/main.bro
Normal file
269
scripts/base/protocols/rdp/main.bro
Normal file
|
@ -0,0 +1,269 @@
|
|||
##! Implements base functionality for RDP analysis. Generates the rdp.log file.
|
||||
|
||||
@load ./consts
|
||||
|
||||
module RDP;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the event happened.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Cookie value used by the client machine.
|
||||
## This is typically a username.
|
||||
cookie: string &log &optional;
|
||||
## Status result for the connection. It's a mix between
|
||||
## RDP negotation failure messages and GCC server create
|
||||
## response messages.
|
||||
result: string &log &optional;
|
||||
## Security protocol chosen by the server.
|
||||
security_protocol: string &log &optional;
|
||||
|
||||
## Keyboard layout (language) of the client machine.
|
||||
keyboard_layout: string &log &optional;
|
||||
## RDP client version used by the client machine.
|
||||
client_build: string &log &optional;
|
||||
## Name of the client machine.
|
||||
client_name: string &log &optional;
|
||||
## Product ID of the client machine.
|
||||
client_dig_product_id: string &log &optional;
|
||||
## Desktop width of the client machine.
|
||||
desktop_width: count &log &optional;
|
||||
## Desktop height of the client machine.
|
||||
desktop_height: count &log &optional;
|
||||
## The color depth requested by the client in
|
||||
## the high_color_depth field.
|
||||
requested_color_depth: string &log &optional;
|
||||
|
||||
## If the connection is being encrypted with native
|
||||
## RDP encryption, this is the type of cert
|
||||
## being used.
|
||||
cert_type: string &log &optional;
|
||||
## The number of certs seen. X.509 can transfer an
|
||||
## entire certificate chain.
|
||||
cert_count: count &log &default=0;
|
||||
## Indicates if the provided certificate or certificate
|
||||
## chain is permanent or temporary.
|
||||
cert_permanent: bool &log &optional;
|
||||
## Encryption level of the connection.
|
||||
encryption_level: string &log &optional;
|
||||
## Encryption method of the connection.
|
||||
encryption_method: string &log &optional;
|
||||
};
|
||||
|
||||
## If true, detach the RDP analyzer from the connection to prevent
|
||||
## continuing to process encrypted traffic.
|
||||
const disable_analyzer_after_detection = F &redef;
|
||||
|
||||
## The amount of time to monitor an RDP session from when it is first
|
||||
## identified. When this interval is reached, the session is logged.
|
||||
const rdp_check_interval = 10secs &redef;
|
||||
|
||||
## Event that can be handled to access the rdp record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_rdp: event(rec: Info);
|
||||
}
|
||||
|
||||
# Internal fields that aren't useful externally
|
||||
redef record Info += {
|
||||
## The analyzer ID used for the analyzer instance attached
|
||||
## to each connection. It is not used for logging since it's a
|
||||
## meaningless arbitrary number.
|
||||
analyzer_id: count &optional;
|
||||
## Track status of logging RDP connections.
|
||||
done: bool &default=F;
|
||||
};
|
||||
|
||||
redef record connection += {
|
||||
rdp: Info &optional;
|
||||
};
|
||||
|
||||
const ports = { 3389/tcp };
|
||||
redef likely_server_ports += { ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(RDP::LOG, [$columns=RDP::Info, $ev=log_rdp, $path="rdp"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, ports);
|
||||
}
|
||||
|
||||
function write_log(c: connection)
|
||||
{
|
||||
local info = c$rdp;
|
||||
|
||||
if ( info$done )
|
||||
return;
|
||||
|
||||
# Mark this record as fully logged and finished.
|
||||
info$done = T;
|
||||
|
||||
# Verify that the RDP session contains
|
||||
# RDP data before writing it to the log.
|
||||
if ( info?$cookie || info?$keyboard_layout || info?$result )
|
||||
Log::write(RDP::LOG, info);
|
||||
}
|
||||
|
||||
event check_record(c: connection)
|
||||
{
|
||||
# If the record was logged, then stop processing.
|
||||
if ( c$rdp$done )
|
||||
return;
|
||||
|
||||
# If the value rdp_check_interval has passed since the
|
||||
# RDP session was started, then log the record.
|
||||
local diff = network_time() - c$rdp$ts;
|
||||
if ( diff > rdp_check_interval )
|
||||
{
|
||||
write_log(c);
|
||||
|
||||
# Remove the analyzer if it is still attached.
|
||||
if ( disable_analyzer_after_detection &&
|
||||
connection_exists(c$id) &&
|
||||
c$rdp?$analyzer_id )
|
||||
{
|
||||
disable_analyzer(c$id, c$rdp$analyzer_id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
# If the analyzer is attached and the duration
|
||||
# to monitor the RDP session was not met, then
|
||||
# reschedule the logging event.
|
||||
schedule rdp_check_interval { check_record(c) };
|
||||
}
|
||||
}
|
||||
|
||||
function set_session(c: connection)
|
||||
{
|
||||
if ( ! c?$rdp )
|
||||
{
|
||||
c$rdp = [$ts=network_time(),$id=c$id,$uid=c$uid];
|
||||
# The RDP session is scheduled to be logged from
|
||||
# the time it is first initiated.
|
||||
schedule rdp_check_interval { check_record(c) };
|
||||
}
|
||||
}
|
||||
|
||||
event rdp_connect_request(c: connection, cookie: string) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$cookie = cookie;
|
||||
}
|
||||
|
||||
event rdp_negotiation_response(c: connection, security_protocol: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$security_protocol = security_protocols[security_protocol];
|
||||
}
|
||||
|
||||
event rdp_negotiation_failure(c: connection, failure_code: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$result = failure_codes[failure_code];
|
||||
}
|
||||
|
||||
event rdp_client_core_data(c: connection, data: RDP::ClientCoreData) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$keyboard_layout = RDP::languages[data$keyboard_layout];
|
||||
c$rdp$client_build = RDP::builds[data$client_build];
|
||||
c$rdp$client_name = data$client_name;
|
||||
c$rdp$client_dig_product_id = data$dig_product_id;
|
||||
c$rdp$desktop_width = data$desktop_width;
|
||||
c$rdp$desktop_height = data$desktop_height;
|
||||
|
||||
if ( data?$ec_flags && data$ec_flags$want_32bpp_session )
|
||||
c$rdp$requested_color_depth = "32bit";
|
||||
else
|
||||
c$rdp$requested_color_depth = RDP::high_color_depths[data$high_color_depth];
|
||||
}
|
||||
|
||||
event rdp_gcc_server_create_response(c: connection, result: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$result = RDP::results[result];
|
||||
}
|
||||
|
||||
event rdp_server_security(c: connection, encryption_method: count, encryption_level: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$encryption_method = RDP::encryption_methods[encryption_method];
|
||||
c$rdp$encryption_level = RDP::encryption_levels[encryption_level];
|
||||
}
|
||||
|
||||
event rdp_server_certificate(c: connection, cert_type: count, permanently_issued: bool) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$rdp$cert_type = RDP::cert_types[cert_type];
|
||||
|
||||
# There are no events for proprietary/RSA certs right
|
||||
# now so we manually count this one.
|
||||
if ( c$rdp$cert_type == "RSA" )
|
||||
++c$rdp$cert_count;
|
||||
|
||||
c$rdp$cert_permanent = permanently_issued;
|
||||
}
|
||||
|
||||
event rdp_begin_encryption(c: connection, security_protocol: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
if ( ! c$rdp?$result )
|
||||
{
|
||||
c$rdp$result = "encrypted";
|
||||
}
|
||||
|
||||
c$rdp$security_protocol = security_protocols[security_protocol];
|
||||
}
|
||||
|
||||
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5
|
||||
{
|
||||
if ( c?$rdp && f$source == "RDP" )
|
||||
{
|
||||
# Count up X509 certs.
|
||||
++c$rdp$cert_count;
|
||||
|
||||
Files::add_analyzer(f, Files::ANALYZER_X509);
|
||||
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
||||
Files::add_analyzer(f, Files::ANALYZER_SHA1);
|
||||
}
|
||||
}
|
||||
|
||||
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5
|
||||
{
|
||||
if ( atype == Analyzer::ANALYZER_RDP )
|
||||
{
|
||||
set_session(c);
|
||||
c$rdp$analyzer_id = aid;
|
||||
}
|
||||
}
|
||||
|
||||
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count, reason: string) &priority=5
|
||||
{
|
||||
# If a protocol violation occurs, then log the record immediately.
|
||||
if ( c?$rdp )
|
||||
write_log(c);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
# If the connection is removed, then log the record immediately.
|
||||
if ( c?$rdp )
|
||||
{
|
||||
write_log(c);
|
||||
}
|
||||
}
|
|
@ -92,7 +92,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp]);
|
||||
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp, $path="smtp"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SMTP, ports);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ redef likely_server_ports += { ports };
|
|||
event bro_init() &priority=5
|
||||
{
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SNMP, ports);
|
||||
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp]);
|
||||
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp, $path="snmp"]);
|
||||
}
|
||||
|
||||
function init_state(c: connection, h: SNMP::Header): Info
|
||||
|
|
|
@ -16,8 +16,10 @@ export {
|
|||
id: conn_id &log;
|
||||
## Protocol version of SOCKS.
|
||||
version: count &log;
|
||||
## Username for the proxy if extracted from the network.
|
||||
## Username used to request a login to the proxy.
|
||||
user: string &log &optional;
|
||||
## Password used to request a login to the proxy.
|
||||
password: string &log &optional;
|
||||
## Server status for the attempt at using the proxy.
|
||||
status: string &log &optional;
|
||||
## Client requested SOCKS address. Could be an address, a name
|
||||
|
@ -41,7 +43,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks]);
|
||||
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks, $path="socks"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SOCKS, ports);
|
||||
}
|
||||
|
||||
|
@ -91,3 +93,21 @@ event socks_reply(c: connection, version: count, reply: count, sa: SOCKS::Addres
|
|||
if ( "SOCKS" in c$service )
|
||||
Log::write(SOCKS::LOG, c$socks);
|
||||
}
|
||||
|
||||
event socks_login_userpass_request(c: connection, user: string, password: string) &priority=5
|
||||
{
|
||||
# Authentication only possible with the version 5.
|
||||
set_session(c, 5);
|
||||
|
||||
c$socks$user = user;
|
||||
c$socks$password = password;
|
||||
}
|
||||
|
||||
event socks_login_userpass_reply(c: connection, code: count) &priority=5
|
||||
{
|
||||
# Authentication only possible with the version 5.
|
||||
set_session(c, 5);
|
||||
|
||||
c$socks$status = v5_status[code];
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Support for Secure Shell (SSH) protocol analysis.
|
|
@ -1,3 +1,2 @@
|
|||
@load ./main
|
||||
|
||||
@load-sigs ./dpd.sig
|
||||
@load-sigs ./dpd.sig
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
signature dpd_ssh_client {
|
||||
ip-proto == tcp
|
||||
payload /^[sS][sS][hH]-/
|
||||
payload /^[sS][sS][hH]-[12]\./
|
||||
requires-reverse-signature dpd_ssh_server
|
||||
enable "ssh"
|
||||
tcp-state originator
|
||||
|
@ -8,6 +8,6 @@ signature dpd_ssh_client {
|
|||
|
||||
signature dpd_ssh_server {
|
||||
ip-proto == tcp
|
||||
payload /^[sS][sS][hH]-/
|
||||
payload /^[sS][sS][hH]-[12]\./
|
||||
tcp-state responder
|
||||
}
|
||||
}
|
|
@ -1,15 +1,5 @@
|
|||
##! Base SSH analysis script. The heuristic to blindly determine success or
|
||||
##! failure for SSH connections is implemented here. At this time, it only
|
||||
##! uses the size of the data being returned from the server to make the
|
||||
##! heuristic determination about success of the connection.
|
||||
##! Requires that :bro:id:`use_conn_size_analyzer` is set to T! The heuristic
|
||||
##! is not attempted if the connection size analyzer isn't enabled.
|
||||
##! Implements base functionality for SSH analysis. Generates the ssh.log file.
|
||||
|
||||
@load base/protocols/conn
|
||||
@load base/frameworks/notice
|
||||
@load base/utils/site
|
||||
@load base/utils/thresholds
|
||||
@load base/utils/conn-ids
|
||||
@load base/utils/directions-and-hosts
|
||||
|
||||
module SSH;
|
||||
|
@ -25,45 +15,63 @@ export {
|
|||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Indicates if the login was heuristically guessed to be
|
||||
## "success", "failure", or "undetermined".
|
||||
status: string &log &default="undetermined";
|
||||
## Direction of the connection. If the client was a local host
|
||||
## SSH major version (1 or 2)
|
||||
version: count &log;
|
||||
## Authentication result (T=success, F=failure, unset=unknown)
|
||||
auth_success: bool &log &optional;
|
||||
## Direction of the connection. If the client was a local host
|
||||
## logging into an external host, this would be OUTBOUND. INBOUND
|
||||
## would be set for the opposite situation.
|
||||
# TODO: handle local-local and remote-remote better.
|
||||
# TODO - handle local-local and remote-remote better.
|
||||
direction: Direction &log &optional;
|
||||
## Software string from the client.
|
||||
## The client's version string
|
||||
client: string &log &optional;
|
||||
## Software string from the server.
|
||||
## The server's version string
|
||||
server: string &log &optional;
|
||||
## Indicate if the SSH session is done being watched.
|
||||
done: bool &default=F;
|
||||
## The encryption algorithm in use
|
||||
cipher_alg: string &log &optional;
|
||||
## The signing (MAC) algorithm in use
|
||||
mac_alg: string &log &optional;
|
||||
## The compression algorithm in use
|
||||
compression_alg: string &log &optional;
|
||||
## The key exchange algorithm in use
|
||||
kex_alg: string &log &optional;
|
||||
## The server host key's algorithm
|
||||
host_key_alg: string &log &optional;
|
||||
## The server's key fingerprint
|
||||
host_key: string &log &optional;
|
||||
};
|
||||
|
||||
## The size in bytes of data sent by the server at which the SSH
|
||||
## connection is presumed to be successful.
|
||||
const authentication_data_size = 4000 &redef;
|
||||
## The set of compression algorithms. We can't accurately determine
|
||||
## authentication success or failure when compression is enabled.
|
||||
const compression_algorithms = set("zlib", "zlib@openssh.com") &redef;
|
||||
|
||||
## If true, we tell the event engine to not look at further data
|
||||
## packets after the initial SSH handshake. Helps with performance
|
||||
## (especially with large file transfers) but precludes some
|
||||
## kinds of analyses.
|
||||
const skip_processing_after_detection = F &redef;
|
||||
## kinds of analyses. Defaults to T.
|
||||
const skip_processing_after_detection = T &redef;
|
||||
|
||||
## Event that is generated when the heuristic thinks that a login
|
||||
## was successful.
|
||||
global heuristic_successful_login: event(c: connection);
|
||||
|
||||
## Event that is generated when the heuristic thinks that a login
|
||||
## failed.
|
||||
global heuristic_failed_login: event(c: connection);
|
||||
|
||||
## Event that can be handled to access the :bro:type:`SSH::Info`
|
||||
## record as it is sent on to the logging framework.
|
||||
## Event that can be handled to access the SSH record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_ssh: event(rec: Info);
|
||||
|
||||
## Event that can be handled when the analyzer sees an SSH server host
|
||||
## key. This abstracts :bro:id:`ssh1_server_host_key` and
|
||||
## :bro:id:`ssh2_server_host_key`.
|
||||
global ssh_server_host_key: event(c: connection, hash: string);
|
||||
}
|
||||
|
||||
redef record Info += {
|
||||
# This connection has been logged (internal use)
|
||||
logged: bool &default=F;
|
||||
# Number of failures seen (internal use)
|
||||
num_failures: count &default=0;
|
||||
# Store capabilities from the first host for
|
||||
# comparison with the second (internal use)
|
||||
capabilities: Capabilities &optional;
|
||||
};
|
||||
|
||||
redef record connection += {
|
||||
ssh: Info &optional;
|
||||
};
|
||||
|
@ -72,133 +80,152 @@ const ports = { 22/tcp };
|
|||
redef likely_server_ports += { ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh]);
|
||||
{
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SSH, ports);
|
||||
}
|
||||
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh, $path="ssh"]);
|
||||
}
|
||||
|
||||
function set_session(c: connection)
|
||||
{
|
||||
if ( ! c?$ssh )
|
||||
{
|
||||
local info: Info;
|
||||
info$ts=network_time();
|
||||
info$uid=c$uid;
|
||||
info$id=c$id;
|
||||
local info: SSH::Info;
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
c$ssh = info;
|
||||
}
|
||||
}
|
||||
|
||||
function check_ssh_connection(c: connection, done: bool)
|
||||
{
|
||||
# If already done watching this connection, just return.
|
||||
if ( c$ssh$done )
|
||||
return;
|
||||
|
||||
if ( done )
|
||||
{
|
||||
# If this connection is done, then we can look to see if
|
||||
# this matches the conditions for a failed login. Failed
|
||||
# logins are only detected at connection state removal.
|
||||
|
||||
if ( # Require originators and responders to have sent at least 50 bytes.
|
||||
c$orig$size > 50 && c$resp$size > 50 &&
|
||||
# Responders must be below 4000 bytes.
|
||||
c$resp$size < authentication_data_size &&
|
||||
# Responder must have sent fewer than 40 packets.
|
||||
c$resp$num_pkts < 40 &&
|
||||
# If there was a content gap we can't reliably do this heuristic.
|
||||
c?$conn && c$conn$missed_bytes == 0 )# &&
|
||||
# Only "normal" connections can count.
|
||||
#c$conn?$conn_state && c$conn$conn_state in valid_states )
|
||||
{
|
||||
c$ssh$status = "failure";
|
||||
event SSH::heuristic_failed_login(c);
|
||||
}
|
||||
|
||||
if ( c$resp$size >= authentication_data_size )
|
||||
{
|
||||
c$ssh$status = "success";
|
||||
event SSH::heuristic_successful_login(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# If this connection is still being tracked, then it's possible
|
||||
# to watch for it to be a successful connection.
|
||||
if ( c$resp$size >= authentication_data_size )
|
||||
{
|
||||
c$ssh$status = "success";
|
||||
event SSH::heuristic_successful_login(c);
|
||||
}
|
||||
else
|
||||
# This connection must be tracked longer. Let the scheduled
|
||||
# check happen again.
|
||||
return;
|
||||
}
|
||||
|
||||
# Set the direction for the log.
|
||||
c$ssh$direction = Site::is_local_addr(c$id$orig_h) ? OUTBOUND : INBOUND;
|
||||
|
||||
# Set the "done" flag to prevent the watching event from rescheduling
|
||||
# after detection is done.
|
||||
c$ssh$done=T;
|
||||
|
||||
if ( skip_processing_after_detection )
|
||||
{
|
||||
# Stop watching this connection, we don't care about it anymore.
|
||||
skip_further_processing(c$id);
|
||||
set_record_packets(c$id, F);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
event heuristic_successful_login(c: connection) &priority=-5
|
||||
{
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
|
||||
event heuristic_failed_login(c: connection) &priority=-5
|
||||
{
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$ssh )
|
||||
{
|
||||
check_ssh_connection(c, T);
|
||||
if ( c$ssh$status == "undetermined" )
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
}
|
||||
|
||||
event ssh_watcher(c: connection)
|
||||
{
|
||||
local id = c$id;
|
||||
# don't go any further if this connection is gone already!
|
||||
if ( ! connection_exists(id) )
|
||||
return;
|
||||
|
||||
lookup_connection(c$id);
|
||||
check_ssh_connection(c, F);
|
||||
if ( ! c$ssh$done )
|
||||
schedule +15secs { ssh_watcher(c) };
|
||||
}
|
||||
|
||||
event ssh_server_version(c: connection, version: string) &priority=5
|
||||
event ssh_server_version(c: connection, version: string)
|
||||
{
|
||||
set_session(c);
|
||||
c$ssh$server = version;
|
||||
}
|
||||
|
||||
event ssh_client_version(c: connection, version: string) &priority=5
|
||||
event ssh_client_version(c: connection, version: string)
|
||||
{
|
||||
set_session(c);
|
||||
c$ssh$client = version;
|
||||
|
||||
# The heuristic detection for SSH relies on the ConnSize analyzer.
|
||||
# Don't do the heuristics if it's disabled.
|
||||
if ( use_conn_size_analyzer )
|
||||
schedule +15secs { ssh_watcher(c) };
|
||||
if ( ( |version| > 3 ) && ( version[4] == "1" ) )
|
||||
c$ssh$version = 1;
|
||||
if ( ( |version| > 3 ) && ( version[4] == "2" ) )
|
||||
c$ssh$version = 2;
|
||||
}
|
||||
|
||||
event ssh_auth_successful(c: connection, auth_method_none: bool)
|
||||
{
|
||||
# TODO - what to do here?
|
||||
if ( !c?$ssh || ( c$ssh?$auth_success && c$ssh$auth_success ) )
|
||||
return;
|
||||
|
||||
# We can't accurately tell for compressed streams
|
||||
if ( c$ssh?$compression_alg && ( c$ssh$compression_alg in compression_algorithms ) )
|
||||
return;
|
||||
|
||||
c$ssh$auth_success = T;
|
||||
|
||||
if ( skip_processing_after_detection)
|
||||
{
|
||||
skip_further_processing(c$id);
|
||||
set_record_packets(c$id, F);
|
||||
}
|
||||
}
|
||||
|
||||
event ssh_auth_successful(c: connection, auth_method_none: bool) &priority=-5
|
||||
{
|
||||
if ( c?$ssh && !c$ssh$logged )
|
||||
{
|
||||
c$ssh$logged = T;
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
}
|
||||
|
||||
event ssh_auth_failed(c: connection)
|
||||
{
|
||||
if ( !c?$ssh || ( c$ssh?$auth_success && !c$ssh$auth_success ) )
|
||||
return;
|
||||
|
||||
# We can't accurately tell for compressed streams
|
||||
if ( c$ssh?$compression_alg && ( c$ssh$compression_alg in compression_algorithms ) )
|
||||
return;
|
||||
|
||||
c$ssh$auth_success = F;
|
||||
c$ssh$num_failures += 1;
|
||||
}
|
||||
|
||||
# Determine the negotiated algorithm
|
||||
function find_alg(client_algorithms: vector of string, server_algorithms: vector of string): string
|
||||
{
|
||||
for ( i in client_algorithms )
|
||||
for ( j in server_algorithms )
|
||||
if ( client_algorithms[i] == server_algorithms[j] )
|
||||
return client_algorithms[i];
|
||||
return "Algorithm negotiation failed";
|
||||
}
|
||||
|
||||
# This is a simple wrapper around find_alg for cases where client to server and server to client
|
||||
# negotiate different algorithms. This is rare, but provided for completeness.
|
||||
function find_bidirectional_alg(client_prefs: Algorithm_Prefs, server_prefs: Algorithm_Prefs): string
|
||||
{
|
||||
local c_to_s = find_alg(client_prefs$client_to_server, server_prefs$client_to_server);
|
||||
local s_to_c = find_alg(client_prefs$server_to_client, server_prefs$server_to_client);
|
||||
|
||||
# Usually these are the same, but if they're not, return the details
|
||||
return c_to_s == s_to_c ? c_to_s : fmt("To server: %s, to client: %s", c_to_s, s_to_c);
|
||||
}
|
||||
|
||||
event ssh_capabilities(c: connection, cookie: string, capabilities: Capabilities)
|
||||
{
|
||||
if ( !c?$ssh || ( c$ssh?$capabilities && c$ssh$capabilities$is_server == capabilities$is_server ) )
|
||||
return;
|
||||
|
||||
if ( !c$ssh?$capabilities )
|
||||
{
|
||||
c$ssh$capabilities = capabilities;
|
||||
return;
|
||||
}
|
||||
|
||||
local client_caps = capabilities$is_server ? c$ssh$capabilities : capabilities;
|
||||
local server_caps = capabilities$is_server ? capabilities : c$ssh$capabilities;
|
||||
|
||||
c$ssh$cipher_alg = find_bidirectional_alg(client_caps$encryption_algorithms,
|
||||
server_caps$encryption_algorithms);
|
||||
c$ssh$mac_alg = find_bidirectional_alg(client_caps$mac_algorithms,
|
||||
server_caps$mac_algorithms);
|
||||
c$ssh$compression_alg = find_bidirectional_alg(client_caps$compression_algorithms,
|
||||
server_caps$compression_algorithms);
|
||||
c$ssh$kex_alg = find_alg(client_caps$kex_algorithms, server_caps$kex_algorithms);
|
||||
c$ssh$host_key_alg = find_alg(client_caps$server_host_key_algorithms,
|
||||
server_caps$server_host_key_algorithms);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$ssh && !c$ssh$logged && c$ssh?$client && c$ssh?$server )
|
||||
{
|
||||
c$ssh$logged = T;
|
||||
Log::write(SSH::LOG, c$ssh);
|
||||
}
|
||||
}
|
||||
|
||||
function generate_fingerprint(c: connection, key: string)
|
||||
{
|
||||
if ( !c?$ssh )
|
||||
return;
|
||||
|
||||
local lx = str_split(md5_hash(key), vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30));
|
||||
lx[0] = "";
|
||||
c$ssh$host_key = sub(join_string_vec(lx, ":"), /:/, "");
|
||||
}
|
||||
|
||||
event ssh1_server_host_key(c: connection, p: string, e: string) &priority=5
|
||||
{
|
||||
generate_fingerprint(c, e + p);
|
||||
}
|
||||
|
||||
event ssh2_server_host_key(c: connection, key: string) &priority=5
|
||||
{
|
||||
generate_fingerprint(c, key);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,11 @@ export {
|
|||
const TLSv10 = 0x0301;
|
||||
const TLSv11 = 0x0302;
|
||||
const TLSv12 = 0x0303;
|
||||
|
||||
const DTLSv10 = 0xFEFF;
|
||||
# DTLSv11 does not exist
|
||||
const DTLSv12 = 0xFEFD;
|
||||
|
||||
## Mapping between the constants and string values for SSL/TLS versions.
|
||||
const version_strings: table[count] of string = {
|
||||
[SSLv2] = "SSLv2",
|
||||
|
@ -13,6 +18,8 @@ export {
|
|||
[TLSv10] = "TLSv10",
|
||||
[TLSv11] = "TLSv11",
|
||||
[TLSv12] = "TLSv12",
|
||||
[DTLSv10] = "DTLSv10",
|
||||
[DTLSv12] = "DTLSv12"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## TLS content types:
|
||||
|
|
|
@ -13,3 +13,10 @@ signature dpd_ssl_client {
|
|||
payload /^(\x16\x03[\x00\x01\x02\x03]..\x01...\x03[\x00\x01\x02\x03]|...?\x01[\x00\x03][\x00\x01\x02\x03]).*/
|
||||
tcp-state originator
|
||||
}
|
||||
|
||||
signature dpd_dtls_client {
|
||||
ip-proto == udp
|
||||
# Client hello.
|
||||
payload /^\x16\xfe[\xff\xfd]\x00\x00\x00\x00\x00\x00\x00...\x01...........\xfe[\xff\xfd].*/
|
||||
enable "dtls"
|
||||
}
|
||||
|
|
|
@ -85,6 +85,10 @@ event bro_init() &priority=5
|
|||
Files::register_protocol(Analyzer::ANALYZER_SSL,
|
||||
[$get_file_handle = SSL::get_file_handle,
|
||||
$describe = SSL::describe_file]);
|
||||
|
||||
Files::register_protocol(Analyzer::ANALYZER_DTLS,
|
||||
[$get_file_handle = SSL::get_file_handle,
|
||||
$describe = SSL::describe_file]);
|
||||
}
|
||||
|
||||
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5
|
||||
|
|
|
@ -92,16 +92,22 @@ redef record Info += {
|
|||
delay_tokens: set[string] &optional;
|
||||
};
|
||||
|
||||
const ports = {
|
||||
const ssl_ports = {
|
||||
443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
|
||||
989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
|
||||
};
|
||||
redef likely_server_ports += { ports };
|
||||
|
||||
# There are no well known DTLS ports at the moment. Let's
|
||||
# just add 443 for now for good measure - who knows :)
|
||||
const dtls_ports = { 443/udp };
|
||||
|
||||
redef likely_server_ports += { ssl_ports, dtls_ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ports);
|
||||
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ssl_ports);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_DTLS, dtls_ports);
|
||||
}
|
||||
|
||||
function set_session(c: connection)
|
||||
|
@ -268,7 +274,7 @@ event connection_state_remove(c: connection) &priority=-5
|
|||
|
||||
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5
|
||||
{
|
||||
if ( atype == Analyzer::ANALYZER_SSL )
|
||||
if ( atype == Analyzer::ANALYZER_SSL || atype == Analyzer::ANALYZER_DTLS )
|
||||
{
|
||||
set_session(c);
|
||||
c$ssl$analyzer_id = aid;
|
||||
|
@ -278,6 +284,6 @@ event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &pr
|
|||
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
|
||||
reason: string) &priority=5
|
||||
{
|
||||
if ( c?$ssl )
|
||||
if ( c?$ssl && ( atype == Analyzer::ANALYZER_SSL || atype == Analyzer::ANALYZER_DTLS ) )
|
||||
finish(c, T);
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -35,7 +35,7 @@ redef likely_server_ports += { ports };
|
|||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Syslog::LOG, [$columns=Info]);
|
||||
Log::create_stream(Syslog::LOG, [$columns=Info, $path="syslog"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SYSLOG, ports);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue