Merge remote branch 'origin/topic/seth/dns-updates'

* origin/topic/seth/dns-updates:
  Fixed some bugs with capturing data in the base DNS script.
  Some updates to the base DNS script.

Closes #702.
This commit is contained in:
Robin Sommer 2011-12-18 15:18:05 -08:00
commit 0a3e160a8d
4 changed files with 100 additions and 69 deletions

23
CHANGES
View file

@ -1,4 +1,27 @@
2.0-beta-126 | 2011-12-18 15:18:05 -0800
* DNS updates. (Seth Hall)
- Fixed some bugs with capturing data in the base DNS script.
- Answers and TTLs are now vectors.
- A warning that was being generated (dns_reply_seen_after_done)
from transaction ID reuse is fixed.
* SSL updates. (Seth Hall)
- Added is_orig fields to the SSL events and adapted script.
- Added a field named last_alert to the SSL log.
- The x509_certificate function has an is_orig field now instead
of is_server and its position in the argument list has moved.
- A bit of reorganization and cleanup in the core analyzer. (Seth
Hall)
2.0-beta-121 | 2011-12-18 15:10:15 -0800
* Enable warnings for malformed Broxygen xref roles. (Jon Siwek)

View file

@ -1 +1 @@
2.0-beta-121
2.0-beta-126

View file

@ -4,50 +4,50 @@ module DNS;
export {
redef enum Log::ID += { 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;
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;
answers: vector of string &log &optional;
TTLs: vector of interval &log &optional;
## This value indicates if this request/response pair is ready to be logged.
ready: bool &default=F;
total_answers: count &optional;
total_replies: count &optional;
};
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;
};
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).
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
}
@ -58,11 +58,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 +89,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 +102,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 +135,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 +167,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 +181,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 +231,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 +246,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 +255,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 +279,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]);
}

View file

@ -1,5 +1,5 @@
#separator \x09
#path dns
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name QR AA TC RD RA Z TTL answers auth addl
#types time string addr port addr port enum count string count string count string count string bool bool bool bool bool count interval table table table
930613226.529070 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F F T 0 31337.000000 4.3.2.1 - -
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name QR AA TC RD RA Z answers TTLs auth addl
#types time string addr port addr port enum count string count string count string count string bool bool bool bool bool count vector vector table table
930613226.529070 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F F T 0 4.3.2.1 31337.000000 - -