mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 23:28:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/bif_cleanup
Conflicts: src/bro.bif
This commit is contained in:
commit
6c255d13ff
247 changed files with 6038 additions and 3503 deletions
|
@ -1,23 +1,27 @@
|
|||
##! This script can be used to extract either the originator's data or the
|
||||
##! responders data or both. By default nothing is extracted, and in order
|
||||
##! to actually extract data the ``c$extract_orig`` and/or the
|
||||
##! ``c$extract_resp`` variable must be set to T. One way to achieve this
|
||||
##! would be to handle the connection_established event elsewhere and set the
|
||||
##! extract_orig and extract_resp options there. However, there may be trouble
|
||||
##! with the timing due the event queue delay.
|
||||
##! This script does not work well in a cluster context unless it has a
|
||||
##! remotely mounted disk to write the content files to.
|
||||
##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this
|
||||
##! would be to handle the :bro:id:`connection_established` event elsewhere
|
||||
##! and set the ``extract_orig`` and ``extract_resp`` options there.
|
||||
##! However, there may be trouble with the timing due to event queue delay.
|
||||
##!
|
||||
##! .. note::
|
||||
##!
|
||||
##! This script does not work well in a cluster context unless it has a
|
||||
##! remotely mounted disk to write the content files to.
|
||||
|
||||
@load base/utils/files
|
||||
|
||||
module Conn;
|
||||
|
||||
export {
|
||||
## The prefix given to files as they are opened on disk.
|
||||
## The prefix given to files containing extracted connections as they are
|
||||
## opened on disk.
|
||||
const extraction_prefix = "contents" &redef;
|
||||
|
||||
## If this variable is set to T, then all contents of all files will be
|
||||
## extracted.
|
||||
## If this variable is set to ``T``, then all contents of all connections
|
||||
## will be extracted.
|
||||
const default_extract = F &redef;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
module Conn;
|
||||
|
||||
export {
|
||||
## Define inactivty timeouts by the service detected being used over
|
||||
## Define inactivity timeouts by the service detected being used over
|
||||
## the connection.
|
||||
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
|
||||
# For interactive services, allow longer periods of inactivity.
|
||||
|
|
|
@ -1,17 +1,33 @@
|
|||
##! This script manages the tracking/logging of general information regarding
|
||||
##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to
|
||||
##! be interpreted using flow semantics (sequence of packets from a source
|
||||
##! host/post to a destination host/port). Further, ICMP "ports" are to
|
||||
##! be interpreted as the source port meaning the ICMP message type and
|
||||
##! the destination port being the ICMP message code.
|
||||
|
||||
@load base/utils/site
|
||||
|
||||
module Conn;
|
||||
|
||||
export {
|
||||
## The connection logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## The record type which contains column fields of the connection log.
|
||||
type Info: record {
|
||||
## This is the time of the first packet.
|
||||
ts: time &log;
|
||||
## A unique identifier of a connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## The transport layer protocol of the connection.
|
||||
proto: transport_proto &log;
|
||||
## An identification of an application protocol being sent over the
|
||||
## the connection.
|
||||
service: string &log &optional;
|
||||
## How long the connection lasted. For 3-way or 4-way connection
|
||||
## tear-downs, this will not include the final ACK.
|
||||
duration: interval &log &optional;
|
||||
## The number of payload bytes the originator sent. For TCP
|
||||
## this is taken from sequence numbers and might be inaccurate
|
||||
|
@ -51,8 +67,8 @@ export {
|
|||
## have been completed prior to the packet loss.
|
||||
missed_bytes: count &log &default=0;
|
||||
|
||||
## Records the state history of (TCP) connections as
|
||||
## a string of letters.
|
||||
## Records the state history of connections as a string of letters.
|
||||
## For TCP connections the meaning of those letters is:
|
||||
##
|
||||
## ====== ====================================================
|
||||
## Letter Meaning
|
||||
|
@ -71,7 +87,8 @@ export {
|
|||
## originator and lower case then means the responder.
|
||||
## Also, there is compression. We only record one "d" in each direction,
|
||||
## for instance. I.e., we just record that data went in that direction.
|
||||
## This history is not meant to encode how much data that happened to be.
|
||||
## This history is not meant to encode how much data that happened to
|
||||
## be.
|
||||
history: string &log &optional;
|
||||
## Number of packets the originator sent.
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||
|
@ -85,7 +102,9 @@ export {
|
|||
## Number IP level bytes the responder sent. See ``orig_pkts``.
|
||||
resp_ip_bytes: count &log &optional;
|
||||
};
|
||||
|
||||
|
||||
## Event that can be handled to access the :bro:type:`Conn::Info`
|
||||
## record as it is sent on to the logging framework.
|
||||
global log_conn: event(rec: Info);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
module DNS;
|
||||
|
||||
export {
|
||||
const PTR = 12;
|
||||
const EDNS = 41;
|
||||
const ANY = 255;
|
||||
const PTR = 12; ##< RR TYPE value for a domain name pointer.
|
||||
const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
|
||||
const ANY = 255; ##< A QTYPE value describing a request for all records.
|
||||
|
||||
## Mapping of DNS query type codes to human readable string representation.
|
||||
const query_types = {
|
||||
|
@ -29,50 +29,43 @@ export {
|
|||
[ANY] = "*",
|
||||
} &default = function(n: count): string { return fmt("query-%d", n); };
|
||||
|
||||
const code_types = {
|
||||
[0] = "X0",
|
||||
[1] = "Xfmt",
|
||||
[2] = "Xsrv",
|
||||
[3] = "Xnam",
|
||||
[4] = "Ximp",
|
||||
[5] = "X[",
|
||||
} &default="?";
|
||||
|
||||
## Errors used for non-TSIG/EDNS types.
|
||||
const base_errors = {
|
||||
[0] = "NOERROR", ##< No Error
|
||||
[1] = "FORMERR", ##< Format Error
|
||||
[2] = "SERVFAIL", ##< Server Failure
|
||||
[3] = "NXDOMAIN", ##< Non-Existent Domain
|
||||
[4] = "NOTIMP", ##< Not Implemented
|
||||
[5] = "REFUSED", ##< Query Refused
|
||||
[6] = "YXDOMAIN", ##< Name Exists when it should not
|
||||
[7] = "YXRRSET", ##< RR Set Exists when it should not
|
||||
[8] = "NXRRSet", ##< RR Set that should exist does not
|
||||
[9] = "NOTAUTH", ##< Server Not Authoritative for zone
|
||||
[10] = "NOTZONE", ##< Name not contained in zone
|
||||
[11] = "unassigned-11", ##< available for assignment
|
||||
[12] = "unassigned-12", ##< available for assignment
|
||||
[13] = "unassigned-13", ##< available for assignment
|
||||
[14] = "unassigned-14", ##< available for assignment
|
||||
[15] = "unassigned-15", ##< available for assignment
|
||||
[16] = "BADVERS", ##< for EDNS, collision w/ TSIG
|
||||
[17] = "BADKEY", ##< Key not recognized
|
||||
[18] = "BADTIME", ##< Signature out of time window
|
||||
[19] = "BADMODE", ##< Bad TKEY Mode
|
||||
[20] = "BADNAME", ##< Duplicate key name
|
||||
[21] = "BADALG", ##< Algorithm not supported
|
||||
[22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt
|
||||
[3842] = "BADSIG", ##< 16 <= number collision with EDNS(16);
|
||||
##< this is a translation from TSIG(16)
|
||||
[0] = "NOERROR", # No Error
|
||||
[1] = "FORMERR", # Format Error
|
||||
[2] = "SERVFAIL", # Server Failure
|
||||
[3] = "NXDOMAIN", # Non-Existent Domain
|
||||
[4] = "NOTIMP", # Not Implemented
|
||||
[5] = "REFUSED", # Query Refused
|
||||
[6] = "YXDOMAIN", # Name Exists when it should not
|
||||
[7] = "YXRRSET", # RR Set Exists when it should not
|
||||
[8] = "NXRRSet", # RR Set that should exist does not
|
||||
[9] = "NOTAUTH", # Server Not Authoritative for zone
|
||||
[10] = "NOTZONE", # Name not contained in zone
|
||||
[11] = "unassigned-11", # available for assignment
|
||||
[12] = "unassigned-12", # available for assignment
|
||||
[13] = "unassigned-13", # available for assignment
|
||||
[14] = "unassigned-14", # available for assignment
|
||||
[15] = "unassigned-15", # available for assignment
|
||||
[16] = "BADVERS", # for EDNS, collision w/ TSIG
|
||||
[17] = "BADKEY", # Key not recognized
|
||||
[18] = "BADTIME", # Signature out of time window
|
||||
[19] = "BADMODE", # Bad TKEY Mode
|
||||
[20] = "BADNAME", # Duplicate key name
|
||||
[21] = "BADALG", # Algorithm not supported
|
||||
[22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
|
||||
[3842] = "BADSIG", # 16 <= number collision with EDNS(16);
|
||||
# this is a translation from TSIG(16)
|
||||
} &default = function(n: count): string { return fmt("rcode-%d", n); };
|
||||
|
||||
# This deciphers EDNS Z field values.
|
||||
## This deciphers EDNS Z field values.
|
||||
const edns_zfield = {
|
||||
[0] = "NOVALUE", # regular entry
|
||||
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
|
||||
} &default="?";
|
||||
|
||||
## Possible values of the CLASS field in resource records or QCLASS field
|
||||
## in query messages.
|
||||
const classes = {
|
||||
[1] = "C_INTERNET",
|
||||
[2] = "C_CSNET",
|
||||
|
@ -81,4 +74,4 @@ export {
|
|||
[254] = "C_NONE",
|
||||
[255] = "C_ANY",
|
||||
} &default = function(n: count): string { return fmt("qclass-%d", n); };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +1,106 @@
|
|||
##! Base DNS analysis script which tracks and logs DNS queries along with
|
||||
##! their responses.
|
||||
|
||||
@load ./consts
|
||||
|
||||
module DNS;
|
||||
|
||||
export {
|
||||
## The DNS logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
|
||||
## The record type which contains the column fields of the DNS log.
|
||||
type Info: record {
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
proto: transport_proto &log;
|
||||
trans_id: count &log &optional;
|
||||
query: string &log &optional;
|
||||
qclass: count &log &optional;
|
||||
qclass_name: string &log &optional;
|
||||
qtype: count &log &optional;
|
||||
qtype_name: string &log &optional;
|
||||
rcode: count &log &optional;
|
||||
rcode_name: string &log &optional;
|
||||
QR: bool &log &default=F;
|
||||
AA: bool &log &default=F;
|
||||
TC: bool &log &default=F;
|
||||
RD: bool &log &default=F;
|
||||
RA: bool &log &default=F;
|
||||
Z: count &log &default=0;
|
||||
TTL: interval &log &optional;
|
||||
answers: set[string] &log &optional;
|
||||
|
||||
## This value indicates if this request/response pair is ready to be logged.
|
||||
## The earliest time at which a DNS protocol message over the
|
||||
## associated connection is observed.
|
||||
ts: time &log;
|
||||
## A unique identifier of the connection over which DNS messages
|
||||
## are being transferred.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## The transport layer protocol of the connection.
|
||||
proto: transport_proto &log;
|
||||
## A 16 bit identifier assigned by the program that generated the
|
||||
## DNS query. Also used in responses to match up replies to
|
||||
## outstanding queries.
|
||||
trans_id: count &log &optional;
|
||||
## The domain name that is the subject of the DNS query.
|
||||
query: string &log &optional;
|
||||
## The QCLASS value specifying the class of the query.
|
||||
qclass: count &log &optional;
|
||||
## A descriptive name for the class of the query.
|
||||
qclass_name: string &log &optional;
|
||||
## A QTYPE value specifying the type of the query.
|
||||
qtype: count &log &optional;
|
||||
## A descriptive name for the type of the query.
|
||||
qtype_name: string &log &optional;
|
||||
## The response code value in DNS response messages.
|
||||
rcode: count &log &optional;
|
||||
## A descriptive name for the response code value.
|
||||
rcode_name: string &log &optional;
|
||||
## Whether the message is a query (F) or response (T).
|
||||
QR: bool &log &default=F;
|
||||
## The Authoritative Answer bit for response messages specifies that
|
||||
## the responding name server is an authority for the domain name
|
||||
## in the question section.
|
||||
AA: bool &log &default=F;
|
||||
## The Truncation bit specifies that the message was truncated.
|
||||
TC: bool &log &default=F;
|
||||
## The Recursion Desired bit indicates to a name server to recursively
|
||||
## purse the query.
|
||||
RD: bool &log &default=F;
|
||||
## The Recursion Available bit in a response message indicates if
|
||||
## the name server supports recursive queries.
|
||||
RA: bool &log &default=F;
|
||||
## A reserved field that is currently supposed to be zero in all
|
||||
## queries and responses.
|
||||
Z: count &log &default=0;
|
||||
## The set of resource descriptions in answer of the query.
|
||||
answers: vector of string &log &optional;
|
||||
## The caching intervals of the associated RRs described by the
|
||||
## ``answers`` field.
|
||||
TTLs: vector of interval &log &optional;
|
||||
|
||||
## This value indicates if this request/response pair is ready to be
|
||||
## logged.
|
||||
ready: bool &default=F;
|
||||
## The total number of resource records in a reply message's answer
|
||||
## section.
|
||||
total_answers: count &optional;
|
||||
## The total number of resource records in a reply message's answer,
|
||||
## authority, and additional sections.
|
||||
total_replies: count &optional;
|
||||
};
|
||||
|
||||
|
||||
## A record type which tracks the status of DNS queries for a given
|
||||
## :bro:type:`connection`.
|
||||
type State: record {
|
||||
## Indexed by query id, returns Info record corresponding to
|
||||
## query/response which haven't completed yet.
|
||||
pending: table[count] of Info &optional;
|
||||
|
||||
|
||||
## This is the list of DNS responses that have completed based on the
|
||||
## number of responses declared and the number received. The contents
|
||||
## of the set are transaction IDs.
|
||||
finished_answers: set[count] &optional;
|
||||
};
|
||||
|
||||
|
||||
## An event that can be handled to access the :bro:type:`DNS::Info`
|
||||
## record as it is sent to the logging framework.
|
||||
global log_dns: event(rec: Info);
|
||||
|
||||
|
||||
## This is called by the specific dns_*_reply events with a "reply" which
|
||||
## may not represent the full data available from the resource record, but
|
||||
## may not represent the full data available from the resource record, but
|
||||
## it's generally considered a summarization of the response(s).
|
||||
##
|
||||
## c: The connection record for which to fill in DNS reply data.
|
||||
##
|
||||
## msg: The DNS message header information for the response.
|
||||
##
|
||||
## ans: The general information of a RR response.
|
||||
##
|
||||
## reply: The specific response information according to RR type/class.
|
||||
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
|
||||
}
|
||||
|
||||
|
@ -58,11 +110,11 @@ redef record connection += {
|
|||
};
|
||||
|
||||
# DPD configuration.
|
||||
redef capture_filters += {
|
||||
redef capture_filters += {
|
||||
["dns"] = "port 53",
|
||||
["mdns"] = "udp and port 5353",
|
||||
["llmns"] = "udp and port 5355",
|
||||
["netbios-ns"] = "udp port 137",
|
||||
["netbios-ns"] = "udp port 137",
|
||||
};
|
||||
|
||||
const dns_ports = { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp };
|
||||
|
@ -89,7 +141,7 @@ function new_session(c: connection, trans_id: count): Info
|
|||
state$finished_answers=set();
|
||||
c$dns_state = state;
|
||||
}
|
||||
|
||||
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
info$id = c$id;
|
||||
|
@ -102,23 +154,29 @@ function new_session(c: connection, trans_id: count): Info
|
|||
function set_session(c: connection, msg: dns_msg, is_query: bool)
|
||||
{
|
||||
if ( ! c?$dns_state || msg$id !in c$dns_state$pending )
|
||||
{
|
||||
c$dns_state$pending[msg$id] = new_session(c, msg$id);
|
||||
|
||||
# Try deleting this transaction id from the set of finished answers.
|
||||
# Sometimes hosts will reuse ports and transaction ids and this should
|
||||
# be considered to be a legit scenario (although bad practice).
|
||||
delete c$dns_state$finished_answers[msg$id];
|
||||
}
|
||||
|
||||
c$dns = c$dns_state$pending[msg$id];
|
||||
|
||||
c$dns$rcode = msg$rcode;
|
||||
c$dns$rcode_name = base_errors[msg$rcode];
|
||||
|
||||
|
||||
if ( ! is_query )
|
||||
{
|
||||
if ( ! c$dns?$total_answers )
|
||||
c$dns$total_answers = msg$num_answers;
|
||||
|
||||
if ( c$dns?$total_replies &&
|
||||
|
||||
if ( c$dns?$total_replies &&
|
||||
c$dns$total_replies != msg$num_answers + msg$num_addl + msg$num_auth )
|
||||
{
|
||||
event conn_weird("dns_changed_number_of_responses", c,
|
||||
fmt("The declared number of responses changed from %d to %d",
|
||||
event conn_weird("dns_changed_number_of_responses", c,
|
||||
fmt("The declared number of responses changed from %d to %d",
|
||||
c$dns$total_replies,
|
||||
msg$num_answers + msg$num_addl + msg$num_auth));
|
||||
}
|
||||
|
@ -129,27 +187,30 @@ function set_session(c: connection, msg: dns_msg, is_query: bool)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=5
|
||||
{
|
||||
set_session(c, msg, F);
|
||||
|
||||
c$dns$AA = msg$AA;
|
||||
c$dns$RA = msg$RA;
|
||||
c$dns$TTL = ans$TTL;
|
||||
|
||||
if ( ans$answer_type == DNS_ANS )
|
||||
{
|
||||
c$dns$AA = msg$AA;
|
||||
c$dns$RA = msg$RA;
|
||||
|
||||
if ( msg$id in c$dns_state$finished_answers )
|
||||
event conn_weird("dns_reply_seen_after_done", c, "");
|
||||
|
||||
|
||||
if ( reply != "" )
|
||||
{
|
||||
if ( ! c$dns?$answers )
|
||||
c$dns$answers = set();
|
||||
add c$dns$answers[reply];
|
||||
c$dns$answers = vector();
|
||||
c$dns$answers[|c$dns$answers|] = reply;
|
||||
|
||||
if ( ! c$dns?$TTLs )
|
||||
c$dns$TTLs = vector();
|
||||
c$dns$TTLs[|c$dns$TTLs|] = ans$TTL;
|
||||
}
|
||||
|
||||
|
||||
if ( c$dns?$answers && |c$dns$answers| == c$dns$total_answers )
|
||||
{
|
||||
add c$dns_state$finished_answers[c$dns$trans_id];
|
||||
|
@ -158,13 +219,12 @@ event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=-5
|
||||
{
|
||||
if ( c$dns$ready )
|
||||
{
|
||||
Log::write(DNS::LOG, c$dns);
|
||||
add c$dns_state$finished_answers[c$dns$trans_id];
|
||||
# This record is logged and no longer pending.
|
||||
delete c$dns_state$pending[c$dns$trans_id];
|
||||
}
|
||||
|
@ -173,41 +233,41 @@ event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string)
|
|||
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) &priority=5
|
||||
{
|
||||
set_session(c, msg, T);
|
||||
|
||||
|
||||
c$dns$RD = msg$RD;
|
||||
c$dns$TC = msg$TC;
|
||||
c$dns$qclass = qclass;
|
||||
c$dns$qclass_name = classes[qclass];
|
||||
c$dns$qtype = qtype;
|
||||
c$dns$qtype_name = query_types[qtype];
|
||||
|
||||
|
||||
# Decode netbios name queries
|
||||
# Note: I'm ignoring the name type for now. Not sure if this should be
|
||||
# Note: I'm ignoring the name type for now. Not sure if this should be
|
||||
# worked into the query/response in some fashion.
|
||||
if ( c$id$resp_p == 137/udp )
|
||||
query = decode_netbios_name(query);
|
||||
c$dns$query = query;
|
||||
|
||||
|
||||
c$dns$Z = msg$Z;
|
||||
}
|
||||
|
||||
|
||||
event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
|
||||
event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, str: string) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, str);
|
||||
}
|
||||
|
||||
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr,
|
||||
|
||||
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr,
|
||||
astr: string) &priority=5
|
||||
{
|
||||
# TODO: What should we do with astr?
|
||||
event DNS::do_reply(c, msg, ans, fmt("%s", a));
|
||||
}
|
||||
|
||||
|
||||
event dns_NS_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
|
@ -223,12 +283,12 @@ event dns_MX_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string,
|
|||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
}
|
||||
|
||||
|
||||
event dns_PTR_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, name);
|
||||
}
|
||||
|
||||
|
||||
event dns_SOA_reply(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, soa$mname);
|
||||
|
@ -238,7 +298,7 @@ event dns_WKS_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
|||
{
|
||||
event DNS::do_reply(c, msg, ans, "");
|
||||
}
|
||||
|
||||
|
||||
event dns_SRV_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
||||
{
|
||||
event DNS::do_reply(c, msg, ans, "");
|
||||
|
@ -247,17 +307,17 @@ event dns_SRV_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5
|
|||
# TODO: figure out how to handle these
|
||||
#event dns_EDNS(c: connection, msg: dns_msg, ans: dns_answer)
|
||||
# {
|
||||
#
|
||||
#
|
||||
# }
|
||||
#
|
||||
#event dns_EDNS_addl(c: connection, msg: dns_msg, ans: dns_edns_additional)
|
||||
# {
|
||||
#
|
||||
#
|
||||
# }
|
||||
#
|
||||
#event dns_TSIG_addl(c: connection, msg: dns_msg, ans: dns_tsig_additional)
|
||||
# {
|
||||
#
|
||||
#
|
||||
# }
|
||||
|
||||
|
||||
|
@ -271,10 +331,10 @@ event connection_state_remove(c: connection) &priority=-5
|
|||
{
|
||||
if ( ! c?$dns_state )
|
||||
return;
|
||||
|
||||
# If Bro is expiring state, we should go ahead and log all unlogged
|
||||
|
||||
# If Bro is expiring state, we should go ahead and log all unlogged
|
||||
# request/response pairs now.
|
||||
for ( trans_id in c$dns_state$pending )
|
||||
Log::write(DNS::LOG, c$dns_state$pending[trans_id]);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
##! File extraction for FTP.
|
||||
##! File extraction support for FTP.
|
||||
|
||||
@load ./main
|
||||
@load base/utils/files
|
||||
|
@ -6,7 +6,7 @@
|
|||
module FTP;
|
||||
|
||||
export {
|
||||
## Pattern of file mime types to extract from FTP entity bodies.
|
||||
## Pattern of file mime types to extract from FTP transfers.
|
||||
const extract_file_types = /NO_DEFAULT/ &redef;
|
||||
|
||||
## The on-disk prefix for files to be extracted from FTP-data transfers.
|
||||
|
@ -14,10 +14,15 @@ export {
|
|||
}
|
||||
|
||||
redef record Info += {
|
||||
## The file handle for the file to be extracted
|
||||
## On disk file where it was extracted to.
|
||||
extraction_file: file &log &optional;
|
||||
|
||||
## Indicates if the current command/response pair should attempt to
|
||||
## extract the file if a file was transferred.
|
||||
extract_file: bool &default=F;
|
||||
|
||||
## Internal tracking of the total number of files extracted during this
|
||||
## session.
|
||||
num_extracted_files: count &default=0;
|
||||
};
|
||||
|
||||
|
@ -33,7 +38,6 @@ event file_transferred(c: connection, prefix: string, descr: string,
|
|||
if ( extract_file_types in s$mime_type )
|
||||
{
|
||||
s$extract_file = T;
|
||||
add s$tags["extracted_file"];
|
||||
++s$num_extracted_files;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
##! The logging this script does is primarily focused on logging FTP commands
|
||||
##! along with metadata. For example, if files are transferred, the argument
|
||||
##! will take on the full path that the client is at along with the requested
|
||||
##! file name.
|
||||
##!
|
||||
##! TODO:
|
||||
##!
|
||||
##! * Handle encrypted sessions correctly (get an example?)
|
||||
##! file name.
|
||||
|
||||
@load ./utils-commands
|
||||
@load base/utils/paths
|
||||
|
@ -14,38 +10,64 @@
|
|||
module FTP;
|
||||
|
||||
export {
|
||||
## The FTP protocol logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
|
||||
## List of commands that should have their command/response pairs logged.
|
||||
const logged_commands = {
|
||||
"APPE", "DELE", "RETR", "STOR", "STOU", "ACCT"
|
||||
} &redef;
|
||||
|
||||
## This setting changes if passwords used in FTP sessions are captured or not.
|
||||
const default_capture_password = F &redef;
|
||||
|
||||
## User IDs that can be considered "anonymous".
|
||||
const guest_ids = { "anonymous", "ftp", "guest" } &redef;
|
||||
|
||||
type Info: record {
|
||||
## Time when the command was sent.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## User name for the current FTP session.
|
||||
user: string &log &default="<unknown>";
|
||||
## Password for the current FTP session if captured.
|
||||
password: string &log &optional;
|
||||
## Command given by the client.
|
||||
command: string &log &optional;
|
||||
## Argument for the command if one is given.
|
||||
arg: string &log &optional;
|
||||
|
||||
|
||||
## Libmagic "sniffed" file type if the command indicates a file transfer.
|
||||
mime_type: string &log &optional;
|
||||
## Libmagic "sniffed" file description if the command indicates a file transfer.
|
||||
mime_desc: string &log &optional;
|
||||
## Size of the file if the command indicates a file transfer.
|
||||
file_size: count &log &optional;
|
||||
|
||||
## Reply code from the server in response to the command.
|
||||
reply_code: count &log &optional;
|
||||
## Reply message from the server in response to the command.
|
||||
reply_msg: string &log &optional;
|
||||
## Arbitrary tags that may indicate a particular attribute of this command.
|
||||
tags: set[string] &log &default=set();
|
||||
|
||||
## By setting the CWD to '/.', we can indicate that unless something
|
||||
## Current working directory that this session is in. By making
|
||||
## the default value '/.', we can indicate that unless something
|
||||
## more concrete is discovered that the existing but unknown
|
||||
## directory is ok to use.
|
||||
cwd: string &default="/.";
|
||||
|
||||
## Command that is currently waiting for a response.
|
||||
cmdarg: CmdArg &optional;
|
||||
## Queue for commands that have been sent but not yet responded to
|
||||
## are tracked here.
|
||||
pending_commands: PendingCmds;
|
||||
|
||||
## This indicates if the session is in active or passive mode.
|
||||
## Indicates if the session is in active or passive mode.
|
||||
passive: bool &default=F;
|
||||
|
||||
## This determines if the password will be captured for this request.
|
||||
## Determines if the password will be captured for this request.
|
||||
capture_password: bool &default=default_capture_password;
|
||||
};
|
||||
|
||||
|
@ -56,22 +78,12 @@ export {
|
|||
y: count;
|
||||
z: count;
|
||||
};
|
||||
|
||||
# TODO: add this back in some form. raise a notice again?
|
||||
#const excessive_filename_len = 250 &redef;
|
||||
#const excessive_filename_trunc_len = 32 &redef;
|
||||
|
||||
## These are user IDs that can be considered "anonymous".
|
||||
const guest_ids = { "anonymous", "ftp", "guest" } &redef;
|
||||
|
||||
## The list of commands that should have their command/response pairs logged.
|
||||
const logged_commands = {
|
||||
"APPE", "DELE", "RETR", "STOR", "STOU", "ACCT"
|
||||
} &redef;
|
||||
|
||||
## This function splits FTP reply codes into the three constituent
|
||||
## Parse FTP reply codes into the three constituent single digit values.
|
||||
global parse_ftp_reply_code: function(code: count): ReplyCode;
|
||||
|
||||
|
||||
## Event that can be handled to access the :bro:type:`FTP::Info`
|
||||
## record as it is sent on to the logging framework.
|
||||
global log_ftp: event(rec: Info);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,14 +2,22 @@ module FTP;
|
|||
|
||||
export {
|
||||
type CmdArg: record {
|
||||
## Time when the command was sent.
|
||||
ts: time;
|
||||
## Command.
|
||||
cmd: string &default="<unknown>";
|
||||
## Argument for the command if one was given.
|
||||
arg: string &default="";
|
||||
## Counter to track how many commands have been executed.
|
||||
seq: count &default=0;
|
||||
};
|
||||
|
||||
|
||||
## Structure for tracking pending commands in the event that the client
|
||||
## sends a large number of commands before the server has a chance to
|
||||
## reply.
|
||||
type PendingCmds: table[count] of CmdArg;
|
||||
|
||||
|
||||
## Possible response codes for a wide variety of FTP commands.
|
||||
const cmd_reply_code: set[string, count] = {
|
||||
# According to RFC 959
|
||||
["<init>", [120, 220, 421]],
|
||||
|
|
|
@ -8,29 +8,24 @@
|
|||
module HTTP;
|
||||
|
||||
export {
|
||||
## Pattern of file mime types to extract from HTTP entity bodies.
|
||||
## Pattern of file mime types to extract from HTTP response entity bodies.
|
||||
const extract_file_types = /NO_DEFAULT/ &redef;
|
||||
|
||||
## The on-disk prefix for files to be extracted from HTTP entity bodies.
|
||||
const extraction_prefix = "http-item" &redef;
|
||||
|
||||
redef record Info += {
|
||||
## This field can be set per-connection to determine if the entity body
|
||||
## will be extracted. It must be set to T on or before the first
|
||||
## entity_body_data event.
|
||||
extracting_file: bool &default=F;
|
||||
|
||||
## This is the holder for the file handle as the file is being written
|
||||
## to disk.
|
||||
## On-disk file where the response body was extracted to.
|
||||
extraction_file: file &log &optional;
|
||||
};
|
||||
|
||||
redef record State += {
|
||||
entity_bodies: count &default=0;
|
||||
|
||||
## Indicates if the response body is to be extracted or not. Must be
|
||||
## set before or by the first :bro:id:`http_entity_data` event for the
|
||||
## content.
|
||||
extract_file: bool &default=F;
|
||||
};
|
||||
}
|
||||
|
||||
event http_entity_data(c: connection, is_orig: bool, length: count, data: string) &priority=5
|
||||
event http_entity_data(c: connection, is_orig: bool, length: count, data: string) &priority=-5
|
||||
{
|
||||
# Client body extraction is not currently supported in this script.
|
||||
if ( is_orig )
|
||||
|
@ -41,8 +36,12 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string
|
|||
if ( c$http?$mime_type &&
|
||||
extract_file_types in c$http$mime_type )
|
||||
{
|
||||
c$http$extracting_file = T;
|
||||
local suffix = fmt("%s_%d.dat", is_orig ? "orig" : "resp", ++c$http_state$entity_bodies);
|
||||
c$http$extract_file = T;
|
||||
}
|
||||
|
||||
if ( c$http$extract_file )
|
||||
{
|
||||
local suffix = fmt("%s_%d.dat", is_orig ? "orig" : "resp", c$http_state$current_response);
|
||||
local fname = generate_extraction_filename(extraction_prefix, c, suffix);
|
||||
|
||||
c$http$extraction_file = open(fname);
|
||||
|
@ -50,12 +49,12 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string
|
|||
}
|
||||
}
|
||||
|
||||
if ( c$http$extracting_file )
|
||||
if ( c$http?$extraction_file )
|
||||
print c$http$extraction_file, data;
|
||||
}
|
||||
|
||||
event http_end_entity(c: connection, is_orig: bool)
|
||||
{
|
||||
if ( c$http$extracting_file )
|
||||
if ( c$http?$extraction_file )
|
||||
close(c$http$extraction_file);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ export {
|
|||
};
|
||||
|
||||
redef record Info += {
|
||||
## The MD5 sum for a file transferred over HTTP will be stored here.
|
||||
## MD5 sum for a file transferred over HTTP calculated from the
|
||||
## response body.
|
||||
md5: string &log &optional;
|
||||
|
||||
## This value can be set per-transfer to determine per request
|
||||
|
@ -19,8 +20,8 @@ export {
|
|||
## set to T at the time of or before the first chunk of body data.
|
||||
calc_md5: bool &default=F;
|
||||
|
||||
## This boolean value indicates if an MD5 sum is currently being
|
||||
## calculated for the current file transfer.
|
||||
## Indicates if an MD5 sum is being calculated for the current
|
||||
## request/response pair.
|
||||
calculating_md5: bool &default=F;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
##! This script is involved in the identification of file types in HTTP
|
||||
##! response bodies.
|
||||
##! Identification of file types in HTTP response bodies with file content sniffing.
|
||||
|
||||
@load base/frameworks/signatures
|
||||
@load base/frameworks/notice
|
||||
|
@ -15,30 +14,32 @@ module HTTP;
|
|||
|
||||
export {
|
||||
redef enum Notice::Type += {
|
||||
# This notice is thrown when the file extension doesn't
|
||||
# seem to match the file contents.
|
||||
## Indicates when the file extension doesn't seem to match the file contents.
|
||||
Incorrect_File_Type,
|
||||
};
|
||||
|
||||
redef record Info += {
|
||||
## This will record the mime_type identified.
|
||||
## Mime type of response body identified by content sniffing.
|
||||
mime_type: string &log &optional;
|
||||
|
||||
## This indicates that no data of the current file transfer has been
|
||||
## Indicates that no data of the current file transfer has been
|
||||
## seen yet. After the first :bro:id:`http_entity_data` event, it
|
||||
## will be set to T.
|
||||
## will be set to F.
|
||||
first_chunk: bool &default=T;
|
||||
};
|
||||
|
||||
redef enum Tags += {
|
||||
IDENTIFIED_FILE
|
||||
};
|
||||
|
||||
# Create regexes that *should* in be in the urls for specifics mime types.
|
||||
# Notices are thrown if the pattern doesn't match the url for the file type.
|
||||
## Mapping between mime types and regular expressions for URLs
|
||||
## The :bro:enum:`HTTP::Incorrect_File_Type` notice is generated if the pattern
|
||||
## doesn't match the mime type that was discovered.
|
||||
const mime_types_extensions: table[string] of pattern = {
|
||||
["application/x-dosexec"] = /\.([eE][xX][eE]|[dD][lL][lL])/,
|
||||
} &redef;
|
||||
|
||||
## A pattern for filtering out :bro:enum:`HTTP::Incorrect_File_Type` urls
|
||||
## that are not noteworthy before a notice is created. Each
|
||||
## pattern added should match the complete URL (the matched URLs include
|
||||
## "http://" at the beginning).
|
||||
const ignored_incorrect_file_type_urls = /^$/ &redef;
|
||||
}
|
||||
|
||||
event signature_match(state: signature_state, msg: string, data: string) &priority=5
|
||||
|
@ -59,6 +60,10 @@ event signature_match(state: signature_state, msg: string, data: string) &priori
|
|||
c$http?$uri && mime_types_extensions[msg] !in c$http$uri )
|
||||
{
|
||||
local url = build_url_http(c$http);
|
||||
|
||||
if ( url == ignored_incorrect_file_type_urls )
|
||||
return;
|
||||
|
||||
local message = fmt("%s %s %s", msg, c$http$method, url);
|
||||
NOTICE([$note=Incorrect_File_Type,
|
||||
$msg=message,
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
##! Implements base functionality for HTTP analysis. The logging model is
|
||||
##! to log request/response pairs and all relevant metadata together in
|
||||
##! a single record.
|
||||
|
||||
@load base/utils/numbers
|
||||
@load base/utils/files
|
||||
|
||||
|
@ -8,6 +12,7 @@ export {
|
|||
|
||||
## Indicate a type of attack or compromise in the record to be logged.
|
||||
type Tags: enum {
|
||||
## Placeholder.
|
||||
EMPTY
|
||||
};
|
||||
|
||||
|
@ -15,64 +20,69 @@ export {
|
|||
const default_capture_password = F &redef;
|
||||
|
||||
type Info: record {
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## This represents the pipelined depth into the connection of this
|
||||
## Timestamp for when the request happened.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## Represents the pipelined depth into the connection of this
|
||||
## request/response transaction.
|
||||
trans_depth: count &log;
|
||||
## The verb used in the HTTP request (GET, POST, HEAD, etc.).
|
||||
method: string &log &optional;
|
||||
## The value of the HOST header.
|
||||
host: string &log &optional;
|
||||
## The URI used in the request.
|
||||
uri: string &log &optional;
|
||||
## The value of the "referer" header. The comment is deliberately
|
||||
trans_depth: count &log;
|
||||
## Verb used in the HTTP request (GET, POST, HEAD, etc.).
|
||||
method: string &log &optional;
|
||||
## Value of the HOST header.
|
||||
host: string &log &optional;
|
||||
## URI used in the request.
|
||||
uri: string &log &optional;
|
||||
## Value of the "referer" header. The comment is deliberately
|
||||
## misspelled like the standard declares, but the name used here is
|
||||
## "referrer" spelled correctly.
|
||||
referrer: string &log &optional;
|
||||
## The value of the User-Agent header from the client.
|
||||
user_agent: string &log &optional;
|
||||
## The actual uncompressed content size of the data transferred from
|
||||
referrer: string &log &optional;
|
||||
## Value of the User-Agent header from the client.
|
||||
user_agent: string &log &optional;
|
||||
## Actual uncompressed content size of the data transferred from
|
||||
## the client.
|
||||
request_body_len: count &log &default=0;
|
||||
## The actual uncompressed content size of the data transferred from
|
||||
request_body_len: count &log &default=0;
|
||||
## Actual uncompressed content size of the data transferred from
|
||||
## the server.
|
||||
response_body_len: count &log &default=0;
|
||||
## The status code returned by the server.
|
||||
## Status code returned by the server.
|
||||
status_code: count &log &optional;
|
||||
## The status message returned by the server.
|
||||
## Status message returned by the server.
|
||||
status_msg: string &log &optional;
|
||||
## The last 1xx informational reply code returned by the server.
|
||||
## Last seen 1xx informational reply code returned by the server.
|
||||
info_code: count &log &optional;
|
||||
## The last 1xx informational reply message returned by the server.
|
||||
## Last seen 1xx informational reply message returned by the server.
|
||||
info_msg: string &log &optional;
|
||||
## The filename given in the Content-Disposition header
|
||||
## sent by the server.
|
||||
## Filename given in the Content-Disposition header sent by the server.
|
||||
filename: string &log &optional;
|
||||
## This is a set of indicators of various attributes discovered and
|
||||
## A set of indicators of various attributes discovered and
|
||||
## related to a particular request/response pair.
|
||||
tags: set[Tags] &log;
|
||||
|
||||
## The username if basic-auth is performed for the request.
|
||||
## Username if basic-auth is performed for the request.
|
||||
username: string &log &optional;
|
||||
## The password if basic-auth is performed for the request.
|
||||
## Password if basic-auth is performed for the request.
|
||||
password: string &log &optional;
|
||||
|
||||
## This determines if the password will be captured for this request.
|
||||
## Determines if the password will be captured for this request.
|
||||
capture_password: bool &default=default_capture_password;
|
||||
|
||||
## All of the headers that may indicate if the request was proxied.
|
||||
proxied: set[string] &log &optional;
|
||||
};
|
||||
|
||||
## Structure to maintain state for an HTTP connection with multiple
|
||||
## requests and responses.
|
||||
type State: record {
|
||||
## Pending requests.
|
||||
pending: table[count] of Info;
|
||||
current_response: count &default=0;
|
||||
## Current request in the pending queue.
|
||||
current_request: count &default=0;
|
||||
## Current response in the pending queue.
|
||||
current_response: count &default=0;
|
||||
};
|
||||
|
||||
## The list of HTTP headers typically used to indicate a proxied request.
|
||||
## A list of HTTP headers typically used to indicate proxied requests.
|
||||
const proxy_headers: set[string] = {
|
||||
"FORWARDED",
|
||||
"X-FORWARDED-FOR",
|
||||
|
@ -83,6 +93,8 @@ export {
|
|||
"PROXY-CONNECTION",
|
||||
} &redef;
|
||||
|
||||
## Event that can be handled to access the HTTP record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_http: event(rec: Info);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,31 @@
|
|||
module HTTP;
|
||||
|
||||
export {
|
||||
## Given a string containing a series of key-value pairs separated by "=",
|
||||
## this function can be used to parse out all of the key names.
|
||||
##
|
||||
## data: The raw data, such as a URL or cookie value.
|
||||
##
|
||||
## kv_splitter: A regular expression representing the separator between
|
||||
## key-value pairs.
|
||||
##
|
||||
## Returns: A vector of strings containing the keys.
|
||||
global extract_keys: function(data: string, kv_splitter: pattern): string_vec;
|
||||
|
||||
## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle
|
||||
## edge cases such as proxied requests appropriately.
|
||||
##
|
||||
## rec: An :bro:type:`HTTP::Info` record.
|
||||
##
|
||||
## Returns: A URL, not prefixed by "http://".
|
||||
global build_url: function(rec: Info): string;
|
||||
|
||||
## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle
|
||||
## edge cases such as proxied requests appropriately.
|
||||
##
|
||||
## rec: An :bro:type:`HTTP::Info` record.
|
||||
##
|
||||
## Returns: A URL prefixed with "http://".
|
||||
global build_url_http: function(rec: Info): string;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
##! but that connection will actually be between B and C which could be
|
||||
##! analyzed on a different worker.
|
||||
##!
|
||||
##! Example line from IRC server indicating that the DCC SEND is about to start:
|
||||
##! PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A
|
||||
|
||||
# Example line from IRC server indicating that the DCC SEND is about to start:
|
||||
# PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A
|
||||
|
||||
@load ./main
|
||||
@load base/utils/files
|
||||
|
@ -14,24 +15,25 @@
|
|||
module IRC;
|
||||
|
||||
export {
|
||||
redef enum Tag += { EXTRACTED_FILE };
|
||||
|
||||
## Pattern of file mime types to extract from IRC DCC file transfers.
|
||||
const extract_file_types = /NO_DEFAULT/ &redef;
|
||||
|
||||
## The on-disk prefix for files to be extracted from IRC DCC file transfers.
|
||||
## On-disk prefix for files to be extracted from IRC DCC file transfers.
|
||||
const extraction_prefix = "irc-dcc-item" &redef;
|
||||
|
||||
redef record Info += {
|
||||
dcc_file_name: string &log &optional;
|
||||
dcc_file_size: count &log &optional;
|
||||
dcc_mime_type: string &log &optional;
|
||||
## DCC filename requested.
|
||||
dcc_file_name: string &log &optional;
|
||||
## Size of the DCC transfer as indicated by the sender.
|
||||
dcc_file_size: count &log &optional;
|
||||
## Sniffed mime type of the file.
|
||||
dcc_mime_type: string &log &optional;
|
||||
|
||||
## The file handle for the file to be extracted
|
||||
extraction_file: file &log &optional;
|
||||
extraction_file: file &log &optional;
|
||||
|
||||
## A boolean to indicate if the current file transfer should be extraced.
|
||||
extract_file: bool &default=F;
|
||||
## A boolean to indicate if the current file transfer should be extracted.
|
||||
extract_file: bool &default=F;
|
||||
|
||||
## The count of the number of file that have been extracted during the session.
|
||||
num_extracted_files: count &default=0;
|
||||
|
@ -54,8 +56,10 @@ event file_transferred(c: connection, prefix: string, descr: string,
|
|||
if ( extract_file_types == irc$dcc_mime_type )
|
||||
{
|
||||
irc$extract_file = T;
|
||||
add irc$tags[EXTRACTED_FILE];
|
||||
}
|
||||
|
||||
if ( irc$extract_file )
|
||||
{
|
||||
local suffix = fmt("%d.dat", ++irc$num_extracted_files);
|
||||
local fname = generate_extraction_filename(extraction_prefix, c, suffix);
|
||||
irc$extraction_file = open(fname);
|
||||
|
@ -76,7 +80,7 @@ event file_transferred(c: connection, prefix: string, descr: string,
|
|||
Log::write(IRC::LOG, irc);
|
||||
irc$command = tmp;
|
||||
|
||||
if ( irc$extract_file && irc?$extraction_file )
|
||||
if ( irc?$extraction_file )
|
||||
set_contents_file(id, CONTENTS_RESP, irc$extraction_file);
|
||||
|
||||
# Delete these values in case another DCC transfer
|
||||
|
|
|
@ -1,36 +1,38 @@
|
|||
##! This is the script that implements the core IRC analysis support. It only
|
||||
##! logs a very limited subset of the IRC protocol by default. The points
|
||||
##! that it logs at are NICK commands, USER commands, and JOIN commands. It
|
||||
##! log various bits of meta data as indicated in the :bro:type:`Info` record
|
||||
##! along with the command at the command arguments.
|
||||
##! Implements the core IRC analysis support. The logging model is to log
|
||||
##! IRC commands along with the associated response and some additional
|
||||
##! metadata about the connection if it's available.
|
||||
|
||||
module IRC;
|
||||
|
||||
export {
|
||||
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Tag: enum {
|
||||
EMPTY
|
||||
};
|
||||
|
||||
type Info: record {
|
||||
## Timestamp when the command was seen.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## Nick name given for the connection.
|
||||
nick: string &log &optional;
|
||||
## User name given for the connection.
|
||||
user: string &log &optional;
|
||||
channels: set[string] &log &optional;
|
||||
|
||||
|
||||
## Command given by the client.
|
||||
command: string &log &optional;
|
||||
## Value for the command given by the client.
|
||||
value: string &log &optional;
|
||||
## Any additional data for the command.
|
||||
addl: string &log &optional;
|
||||
tags: set[Tag] &log;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the IRC record as it is sent on
|
||||
## to the logging framework.
|
||||
global irc_log: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
## IRC session information.
|
||||
irc: Info &optional;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,15 +14,17 @@
|
|||
module SSH;
|
||||
|
||||
export {
|
||||
## The SSH protocol logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
redef enum Notice::Type += {
|
||||
## This indicates that a heuristically detected "successful" SSH
|
||||
## Indicates that a heuristically detected "successful" SSH
|
||||
## authentication occurred.
|
||||
Login
|
||||
};
|
||||
|
||||
type Info: record {
|
||||
## Time when the SSH connection began.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
|
@ -34,11 +36,11 @@ export {
|
|||
## would be set for the opposite situation.
|
||||
# TODO: handle local-local and remote-remote better.
|
||||
direction: Direction &log &optional;
|
||||
## The software string given by the client.
|
||||
## Software string given by the client.
|
||||
client: string &log &optional;
|
||||
## The software string given by the server.
|
||||
## Software string given by the server.
|
||||
server: string &log &optional;
|
||||
## The amount of data returned from the server. This is currently
|
||||
## Amount of data returned from the server. This is currently
|
||||
## the only measure of the success heuristic and it is logged to
|
||||
## assist analysts looking at the logs to make their own determination
|
||||
## about the success on a case-by-case basis.
|
||||
|
@ -48,8 +50,8 @@ export {
|
|||
done: bool &default=F;
|
||||
};
|
||||
|
||||
## The size in bytes at which the SSH connection is presumed to be
|
||||
## successful.
|
||||
## The size in bytes of data sent by the server at which the SSH
|
||||
## connection is presumed to be successful.
|
||||
const authentication_data_size = 5500 &redef;
|
||||
|
||||
## If true, we tell the event engine to not look at further data
|
||||
|
@ -58,14 +60,16 @@ export {
|
|||
## kinds of analyses (e.g., tracking connection size).
|
||||
const skip_processing_after_detection = F &redef;
|
||||
|
||||
## This event is generated when the heuristic thinks that a login
|
||||
## Event that is generated when the heuristic thinks that a login
|
||||
## was successful.
|
||||
global heuristic_successful_login: event(c: connection);
|
||||
|
||||
## This event is generated when the heuristic thinks that a login
|
||||
## 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.
|
||||
global log_ssh: event(rec: Info);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,65 @@
|
|||
module SSL;
|
||||
|
||||
export {
|
||||
|
||||
const SSLv2 = 0x0002;
|
||||
const SSLv3 = 0x0300;
|
||||
const TLSv10 = 0x0301;
|
||||
const TLSv11 = 0x0302;
|
||||
const TLSv12 = 0x0303;
|
||||
## Mapping between the constants and string values for SSL/TLS versions.
|
||||
const version_strings: table[count] of string = {
|
||||
[SSLv2] = "SSLv2",
|
||||
[SSLv3] = "SSLv3",
|
||||
[TLSv10] = "TLSv10",
|
||||
[TLSv11] = "TLSv11",
|
||||
[TLSv12] = "TLSv12",
|
||||
} &default="UNKNOWN";
|
||||
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
## levels.
|
||||
const alert_levels: table[count] of string = {
|
||||
[1] = "warning",
|
||||
[2] = "fatal",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable strings for alert
|
||||
## descriptions..
|
||||
const alert_descriptions: table[count] of string = {
|
||||
[0] = "close_notify",
|
||||
[10] = "unexpected_message",
|
||||
[20] = "bad_record_mac",
|
||||
[21] = "decryption_failed",
|
||||
[22] = "record_overflow",
|
||||
[30] = "decompression_failure",
|
||||
[40] = "handshake_failure",
|
||||
[41] = "no_certificate",
|
||||
[42] = "bad_certificate",
|
||||
[43] = "unsupported_certificate",
|
||||
[44] = "certificate_revoked",
|
||||
[45] = "certificate_expired",
|
||||
[46] = "certificate_unknown",
|
||||
[47] = "illegal_parameter",
|
||||
[48] = "unknown_ca",
|
||||
[49] = "access_denied",
|
||||
[50] = "decode_error",
|
||||
[51] = "decrypt_error",
|
||||
[60] = "export_restriction",
|
||||
[70] = "protocol_version",
|
||||
[71] = "insufficient_security",
|
||||
[80] = "internal_error",
|
||||
[90] = "user_canceled",
|
||||
[100] = "no_renegotiation",
|
||||
[110] = "unsupported_extension",
|
||||
[111] = "certificate_unobtainable",
|
||||
[112] = "unrecognized_name",
|
||||
[113] = "bad_certificate_status_response",
|
||||
[114] = "bad_certificate_hash_value",
|
||||
[115] = "unknown_psk_identity",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## Mapping between numeric codes and human readable strings for SSL/TLS
|
||||
## extensions.
|
||||
# More information can be found here:
|
||||
# http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
|
||||
const extensions: table[count] of string = {
|
||||
[0] = "server_name",
|
||||
|
@ -31,10 +78,11 @@ export {
|
|||
[13] = "signature_algorithms",
|
||||
[14] = "use_srtp",
|
||||
[35] = "SessionTicket TLS",
|
||||
[13172] = "next_protocol_negotiation",
|
||||
[65281] = "renegotiation_info"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
## SSLv2
|
||||
# SSLv2
|
||||
const SSLv20_CK_RC4_128_WITH_MD5 = 0x010080;
|
||||
const SSLv20_CK_RC4_128_EXPORT40_WITH_MD5 = 0x020080;
|
||||
const SSLv20_CK_RC2_128_CBC_WITH_MD5 = 0x030080;
|
||||
|
@ -43,7 +91,7 @@ export {
|
|||
const SSLv20_CK_DES_64_CBC_WITH_MD5 = 0x060040;
|
||||
const SSLv20_CK_DES_192_EDE3_CBC_WITH_MD5 = 0x0700C0;
|
||||
|
||||
## TLS
|
||||
# TLS
|
||||
const TLS_NULL_WITH_NULL_NULL = 0x0000;
|
||||
const TLS_RSA_WITH_NULL_MD5 = 0x0001;
|
||||
const TLS_RSA_WITH_NULL_SHA = 0x0002;
|
||||
|
@ -260,13 +308,11 @@ export {
|
|||
const SSL_RSA_WITH_DES_CBC_MD5 = 0xFF82;
|
||||
const SSL_RSA_WITH_3DES_EDE_CBC_MD5 = 0xFF83;
|
||||
const TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
|
||||
|
||||
# --- This is a table of all known cipher specs.
|
||||
# --- It can be used for detecting unknown ciphers and for
|
||||
# --- converting the cipher spec constants into a human readable format.
|
||||
|
||||
|
||||
## This is a table of all known cipher specs. It can be used for
|
||||
## detecting unknown ciphers and for converting the cipher spec constants
|
||||
## into a human readable format.
|
||||
const cipher_desc: table[count] of string = {
|
||||
# --- sslv20 ---
|
||||
[SSLv20_CK_RC4_128_EXPORT40_WITH_MD5] =
|
||||
"SSLv20_CK_RC4_128_EXPORT40_WITH_MD5",
|
||||
[SSLv20_CK_RC4_128_WITH_MD5] = "SSLv20_CK_RC4_128_WITH_MD5",
|
||||
|
@ -278,7 +324,6 @@ export {
|
|||
"SSLv20_CK_DES_192_EDE3_CBC_WITH_MD5",
|
||||
[SSLv20_CK_DES_64_CBC_WITH_MD5] = "SSLv20_CK_DES_64_CBC_WITH_MD5",
|
||||
|
||||
# --- TLS ---
|
||||
[TLS_NULL_WITH_NULL_NULL] = "TLS_NULL_WITH_NULL_NULL",
|
||||
[TLS_RSA_WITH_NULL_MD5] = "TLS_RSA_WITH_NULL_MD5",
|
||||
[TLS_RSA_WITH_NULL_SHA] = "TLS_RSA_WITH_NULL_SHA",
|
||||
|
@ -491,7 +536,8 @@ export {
|
|||
[SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2",
|
||||
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2",
|
||||
} &default="UNKNOWN";
|
||||
|
||||
|
||||
## Mapping between the constants and string values for SSL/TLS errors.
|
||||
const x509_errors: table[count] of string = {
|
||||
[0] = "ok",
|
||||
[1] = "unable to get issuer cert",
|
||||
|
@ -526,8 +572,7 @@ export {
|
|||
[30] = "akid issuer serial mismatch",
|
||||
[31] = "keyusage no certsign",
|
||||
[32] = "unable to get crl issuer",
|
||||
[33] = "unhandled critical extension"
|
||||
|
||||
[33] = "unhandled critical extension",
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
##! Base SSL analysis script. This script logs information about the SSL/TLS
|
||||
##! handshaking and encryption establishment process.
|
||||
|
||||
@load ./consts
|
||||
|
||||
module SSL;
|
||||
|
@ -6,31 +9,45 @@ export {
|
|||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Time when the SSL connection began.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## SSL/TLS version the server offered.
|
||||
version: string &log &optional;
|
||||
## SSL/TLS cipher suite the server chose.
|
||||
cipher: string &log &optional;
|
||||
## Value of the Server Name Indicator SSL/TLS extension. It
|
||||
## indicates the server name that the client was requesting.
|
||||
server_name: string &log &optional;
|
||||
## Session ID offered by the client for session resumption.
|
||||
session_id: string &log &optional;
|
||||
## Subject of the X.509 certificate offered by the server.
|
||||
subject: string &log &optional;
|
||||
## NotValidBefore field value from the server certificate.
|
||||
not_valid_before: time &log &optional;
|
||||
## NotValidAfter field value from the serve certificate.
|
||||
not_valid_after: time &log &optional;
|
||||
## Last alert that was seen during the connection.
|
||||
last_alert: string &log &optional;
|
||||
|
||||
## Full binary server certificate stored in DER format.
|
||||
cert: string &optional;
|
||||
## Chain of certificates offered by the server to validate its
|
||||
## complete signing chain.
|
||||
cert_chain: vector of string &optional;
|
||||
|
||||
## This stores the analyzer id used for the analyzer instance attached
|
||||
## to each connection. It is not used for logging since it's a
|
||||
|
||||
## 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;
|
||||
};
|
||||
|
||||
## This is where the default root CA bundle is defined. By loading the
|
||||
## The default root CA bundle. By loading the
|
||||
## mozilla-ca-list.bro script it will be set to Mozilla's root CA list.
|
||||
const root_certs: table[string] of string = {} &redef;
|
||||
|
||||
## If true, detach the SSL analyzer from the connection to prevent
|
||||
## If true, detach the SSL analyzer from the connection to prevent
|
||||
## continuing to process encrypted traffic. Helps with performance
|
||||
## (especially with large file transfers).
|
||||
const disable_analyzer_after_detection = T &redef;
|
||||
|
@ -40,12 +57,9 @@ export {
|
|||
## utility.
|
||||
const openssl_util = "openssl" &redef;
|
||||
|
||||
## Event that can be handled to access the SSL
|
||||
## record as it is sent on to the logging framework.
|
||||
global log_ssl: event(rec: Info);
|
||||
|
||||
const ports = {
|
||||
443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
|
||||
989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
|
||||
} &redef;
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
|
@ -72,6 +86,11 @@ redef capture_filters += {
|
|||
["xmpps"] = "tcp port 5223",
|
||||
};
|
||||
|
||||
const ports = {
|
||||
443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
|
||||
989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
|
||||
};
|
||||
|
||||
redef dpd_config += {
|
||||
[[ANALYZER_SSL]] = [$ports = ports]
|
||||
};
|
||||
|
@ -86,7 +105,7 @@ function set_session(c: connection)
|
|||
if ( ! c?$ssl )
|
||||
c$ssl = [$ts=network_time(), $uid=c$uid, $id=c$id, $cert_chain=vector()];
|
||||
}
|
||||
|
||||
|
||||
function finish(c: connection)
|
||||
{
|
||||
Log::write(SSL::LOG, c$ssl);
|
||||
|
@ -98,29 +117,33 @@ function finish(c: connection)
|
|||
event ssl_client_hello(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
|
||||
# Save the session_id if there is one set.
|
||||
if ( session_id != /^\x00{32}$/ )
|
||||
c$ssl$session_id = bytestring_to_hexstr(session_id);
|
||||
}
|
||||
|
||||
|
||||
event ssl_server_hello(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
|
||||
c$ssl$version = version_strings[version];
|
||||
c$ssl$cipher = cipher_desc[cipher];
|
||||
}
|
||||
|
||||
event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) &priority=5
|
||||
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
|
||||
# We aren't doing anything with client certificates yet.
|
||||
if ( is_orig )
|
||||
return;
|
||||
|
||||
if ( chain_idx == 0 )
|
||||
{
|
||||
# Save the primary cert.
|
||||
c$ssl$cert = der_cert;
|
||||
|
||||
|
||||
# Also save other certificate information about the primary cert.
|
||||
c$ssl$subject = cert$subject;
|
||||
c$ssl$not_valid_before = cert$not_valid_before;
|
||||
|
@ -132,20 +155,27 @@ event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: co
|
|||
c$ssl$cert_chain[|c$ssl$cert_chain|] = der_cert;
|
||||
}
|
||||
}
|
||||
|
||||
event ssl_extension(c: connection, code: count, val: string) &priority=5
|
||||
|
||||
event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
if ( extensions[code] == "server_name" )
|
||||
|
||||
if ( is_orig && extensions[code] == "server_name" )
|
||||
c$ssl$server_name = sub_bytes(val, 6, |val|);
|
||||
}
|
||||
|
||||
|
||||
event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
|
||||
c$ssl$last_alert = alert_descriptions[desc];
|
||||
}
|
||||
|
||||
event ssl_established(c: connection) &priority=5
|
||||
{
|
||||
set_session(c);
|
||||
}
|
||||
|
||||
|
||||
event ssl_established(c: connection) &priority=-5
|
||||
{
|
||||
finish(c);
|
||||
|
@ -163,4 +193,4 @@ event protocol_violation(c: connection, atype: count, aid: count,
|
|||
{
|
||||
if ( c?$ssl )
|
||||
finish(c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
##! Constants definitions for syslog.
|
||||
|
||||
module Syslog;
|
||||
|
||||
export {
|
||||
## Mapping between the constants and string values for syslog facilities.
|
||||
const facility_codes: table[count] of string = {
|
||||
[0] = "KERN",
|
||||
[1] = "USER",
|
||||
|
@ -27,7 +30,8 @@ export {
|
|||
[22] = "LOCAL6",
|
||||
[23] = "LOCAL7",
|
||||
} &default=function(c: count): string { return fmt("?-%d", c); };
|
||||
|
||||
|
||||
## Mapping between the constants and string values for syslog severities.
|
||||
const severity_codes: table[count] of string = {
|
||||
[0] = "EMERG",
|
||||
[1] = "ALERT",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
##! Core script support for logging syslog messages.
|
||||
##! Core script support for logging syslog messages. This script represents
|
||||
##! one syslog message as one logged record.
|
||||
|
||||
@load ./consts
|
||||
|
||||
|
@ -8,19 +9,23 @@ export {
|
|||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp of when the syslog message was seen.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## Protocol over which the message was seen.
|
||||
proto: transport_proto &log;
|
||||
## Syslog facility for the message.
|
||||
facility: string &log;
|
||||
## Syslog severity for the message.
|
||||
severity: string &log;
|
||||
## The plain text message.
|
||||
message: string &log;
|
||||
};
|
||||
|
||||
const ports = { 514/udp } &redef;
|
||||
}
|
||||
|
||||
redef capture_filters += { ["syslog"] = "port 514" };
|
||||
const ports = { 514/udp } &redef;
|
||||
redef dpd_config += { [ANALYZER_SYSLOG_BINPAC] = [$ports = ports] };
|
||||
|
||||
redef likely_server_ports += { 514/udp };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue