add EDNS cookie parsing

This commit is contained in:
FlyingWithJerome 2020-08-15 19:46:03 -04:00
parent c5b4311a82
commit 74efbd0abc
8 changed files with 95 additions and 2 deletions

View file

@ -3708,6 +3708,14 @@ type dns_edns_tcp_keepalive: record {
keepalive_timeout: count; ##< Timeout value, in 100ms keepalive_timeout: count; ##< Timeout value, in 100ms
}; };
## An DNS EDNS COOKIE (COOKIE) record.
##
## .. zeek:see:: dns_EDNS_tcp_keepalive
type dns_edns_cookie: record {
client_cookie: string; ##< Cookie from the client (fixed 8 bytes)
server_cookie: string &default=""; ##< Cookie from the server (8 to 32 bytes)
};
## An additional DNS TSIG record. ## An additional DNS TSIG record.
## ##
## .. zeek:see:: dns_TSIG_addl ## .. zeek:see:: dns_TSIG_addl

View file

@ -110,6 +110,7 @@ export {
[20] = "BADNAME", # Duplicate key name [20] = "BADNAME", # Duplicate key name
[21] = "BADALG", # Algorithm not supported [21] = "BADALG", # Algorithm not supported
[22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt [22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
[23] = "BADCOOKIE", # Bad EDNS cookie value
[3842] = "BADSIG", # 16 <= number collision with EDNS(16); [3842] = "BADSIG", # 16 <= number collision with EDNS(16);
# this is a translation from TSIG(16) # this is a translation from TSIG(16)
} &default = function(n: count): string { return fmt("rcode-%d", n); }; } &default = function(n: count): string { return fmt("rcode-%d", n); };

View file

@ -109,6 +109,7 @@ zeek::RecordType* dns_soa;
zeek::RecordType* dns_edns_additional; zeek::RecordType* dns_edns_additional;
zeek::RecordType* dns_edns_ecs; zeek::RecordType* dns_edns_ecs;
zeek::RecordType* dns_edns_tcp_keepalive; zeek::RecordType* dns_edns_tcp_keepalive;
zeek::RecordType* dns_edns_cookie;
zeek::RecordType* dns_tsig_additional; zeek::RecordType* dns_tsig_additional;
zeek::RecordType* dns_rrsig_rr; zeek::RecordType* dns_rrsig_rr;
zeek::RecordType* dns_dnskey_rr; zeek::RecordType* dns_dnskey_rr;

View file

@ -153,6 +153,8 @@ extern zeek::RecordType* dns_edns_ecs;
[[deprecated("Remove in v4.1. Perform your own lookup.")]] [[deprecated("Remove in v4.1. Perform your own lookup.")]]
extern zeek::RecordType* dns_edns_tcp_keepalive; extern zeek::RecordType* dns_edns_tcp_keepalive;
[[deprecated("Remove in v4.1. Perform your own lookup.")]] [[deprecated("Remove in v4.1. Perform your own lookup.")]]
extern zeek::RecordType* dns_edns_cookie;
[[deprecated("Remove in v4.1. Perform your own lookup.")]]
extern zeek::RecordType* dns_tsig_additional; extern zeek::RecordType* dns_tsig_additional;
[[deprecated("Remove in v4.1. Perform your own lookup.")]] [[deprecated("Remove in v4.1. Perform your own lookup.")]]
extern zeek::RecordType* dns_rrsig_rr; extern zeek::RecordType* dns_rrsig_rr;

View file

@ -810,14 +810,50 @@ bool DNS_Interpreter::ParseRR_EDNS(DNS_MsgInfo* msg,
msg->BuildHdrVal(), msg->BuildHdrVal(),
msg->BuildEDNS_TCP_KA_Val(&edns_tcp_keepalive) msg->BuildEDNS_TCP_KA_Val(&edns_tcp_keepalive)
); );
break;
} }
else else
{ {
break; // error. MUST BE 0 or 2 bytes // error. MUST BE 0 or 2 bytes
} }
data += option_len;
break;
} // END EDNS TCP KEEPALIVE } // END EDNS TCP KEEPALIVE
case TYPE_COOKIE:
{
EDNS_COOKIE cookie{};
if (option_len != 8 && !(option_len >= 16 && option_len <= 40)) {
/*
* option length for DNS Cookie must be 8 bytes (with client cookie only)
* OR
* between 16 bytes to 40 bytes (with an 8 bytes client and an 8 to 32 bytes
* server cookie)
*/
break;
}
int remaining_cookie_len = option_len;
int client_cookie_len = 8;
cookie.client_cookie = ExtractStream(data, client_cookie_len, client_cookie_len);
cookie.server_cookie = nullptr;
remaining_cookie_len -= 8;
if (remaining_cookie_len >= 8) {
cookie.server_cookie = ExtractStream(data, remaining_cookie_len, remaining_cookie_len);
}
analyzer->EnqueueConnEvent(dns_EDNS_cookie,
analyzer->ConnVal(),
msg->BuildHdrVal(),
msg->BuildEDNS_COOKIE_Val(&cookie)
);
data += option_len;
break;
} // END EDNS COOKIE
default: default:
{ {
data += option_len; data += option_len;
@ -1649,6 +1685,19 @@ zeek::RecordValPtr DNS_MsgInfo::BuildEDNS_TCP_KA_Val(struct EDNS_TCP_KEEPALIVE*
return r; return r;
} }
zeek::RecordValPtr DNS_MsgInfo::BuildEDNS_COOKIE_Val(struct EDNS_COOKIE* opt)
{
static auto dns_edns_cookie = zeek::id::find_type<zeek::RecordType>("dns_edns_cookie");
auto r = zeek::make_intrusive<zeek::RecordVal>(dns_edns_cookie);
r->Assign(0, zeek::make_intrusive<zeek::StringVal>(opt->client_cookie));
if (opt->server_cookie != nullptr) {
r->Assign(1, zeek::make_intrusive<zeek::StringVal>(opt->server_cookie));
}
return r;
}
zeek::RecordValPtr DNS_MsgInfo::BuildTSIG_Val(struct TSIG_DATA* tsig) zeek::RecordValPtr DNS_MsgInfo::BuildTSIG_Val(struct TSIG_DATA* tsig)
{ {
static auto dns_tsig_additional = zeek::id::find_type<zeek::RecordType>("dns_tsig_additional"); static auto dns_tsig_additional = zeek::id::find_type<zeek::RecordType>("dns_tsig_additional");

View file

@ -29,6 +29,7 @@ typedef enum {
DNS_CODE_NAME_ERR = 3, ///< no such domain DNS_CODE_NAME_ERR = 3, ///< no such domain
DNS_CODE_NOT_IMPL = 4, ///< not implemented DNS_CODE_NOT_IMPL = 4, ///< not implemented
DNS_CODE_REFUSED = 5, ///< refused DNS_CODE_REFUSED = 5, ///< refused
DNS_CODE_BADCOOKIE = 23, ///< Bad cookie value (RFC 7873, IANA early allocation)
} DNS_Code; } DNS_Code;
typedef enum { typedef enum {
@ -92,6 +93,7 @@ typedef enum {
TYPE_N3U = 7, ///< RFC6975 TYPE_N3U = 7, ///< RFC6975
TYPE_ECS = 8, ///< RFC7871 TYPE_ECS = 8, ///< RFC7871
TYPE_EXPIRE = 9, ///< RFC7314 TYPE_EXPIRE = 9, ///< RFC7314
TYPE_COOKIE = 10, ///< RFC7873
TYPE_TCP_KA = 11, ///< RFC7828 TYPE_TCP_KA = 11, ///< RFC7828
TYPE_PAD = 12, ///< RFC7830 TYPE_PAD = 12, ///< RFC7830
TYPE_CHAIN = 13, ///< RFC7901 TYPE_CHAIN = 13, ///< RFC7901
@ -161,6 +163,11 @@ struct EDNS_TCP_KEEPALIVE {
uint16_t keepalive_timeout; // the timeout value (in 100ms) sent by the client/server uint16_t keepalive_timeout; // the timeout value (in 100ms) sent by the client/server
}; };
struct EDNS_COOKIE {
zeek::String* client_cookie;
zeek::String* server_cookie;
};
struct TSIG_DATA { struct TSIG_DATA {
zeek::String* alg_name; zeek::String* alg_name;
unsigned long time_s; unsigned long time_s;
@ -217,6 +224,7 @@ public:
zeek::RecordValPtr BuildEDNS_Val(); zeek::RecordValPtr BuildEDNS_Val();
zeek::RecordValPtr BuildEDNS_ECS_Val(struct EDNS_ECS*); zeek::RecordValPtr BuildEDNS_ECS_Val(struct EDNS_ECS*);
zeek::RecordValPtr BuildEDNS_TCP_KA_Val(struct EDNS_TCP_KEEPALIVE*); zeek::RecordValPtr BuildEDNS_TCP_KA_Val(struct EDNS_TCP_KEEPALIVE*);
zeek::RecordValPtr BuildEDNS_COOKIE_Val(struct EDNS_COOKIE*);
zeek::RecordValPtr BuildTSIG_Val(struct TSIG_DATA*); zeek::RecordValPtr BuildTSIG_Val(struct TSIG_DATA*);
zeek::RecordValPtr BuildRRSIG_Val(struct RRSIG_DATA*); zeek::RecordValPtr BuildRRSIG_Val(struct RRSIG_DATA*);
zeek::RecordValPtr BuildDNSKEY_Val(struct DNSKEY_DATA*); zeek::RecordValPtr BuildDNSKEY_Val(struct DNSKEY_DATA*);

View file

@ -551,6 +551,29 @@ event dns_EDNS_ecs%(c: connection, msg: dns_msg, opt: dns_edns_ecs%);
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth ## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_EDNS_tcp_keepalive%(c: connection, msg: dns_msg, opt: dns_edns_tcp_keepalive%); event dns_EDNS_tcp_keepalive%(c: connection, msg: dns_msg, opt: dns_edns_tcp_keepalive%);
## Generated for DNS replies of type *EDNS*. For replies with multiple options,
## an individual event is raised for each.
##
## See `Wikipedia <http://en.wikipedia.org/wiki/Domain_Name_System>`__ for more
## information about the DNS protocol. Zeek analyzes both UDP and TCP DNS
## sessions.
##
## c: The connection, which may be UDP or TCP depending on the type of the
## transport-layer session being analyzed.
##
## msg: The parsed DNS message header.
##
## opt: The parsed EDNS option.
##
## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply dns_MX_reply
## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
## dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_mapping_altered
## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
## dns_max_queries dns_session_timeout dns_skip_addl
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_EDNS_cookie%(c: connection, msg: dns_msg, opt: dns_edns_cookie%);
## Generated for DNS replies of type *TSIG*. For replies with multiple answers, ## Generated for DNS replies of type *TSIG*. For replies with multiple answers,
## an individual event of the corresponding type is raised for each. ## an individual event of the corresponding type is raised for each.
## ##

View file

@ -44,6 +44,7 @@ void zeek_legacy_netvar_init()
::dns_edns_additional = zeek::id::find_type("dns_edns_additional")->AsRecordType(); ::dns_edns_additional = zeek::id::find_type("dns_edns_additional")->AsRecordType();
::dns_edns_ecs = zeek::id::find_type("dns_edns_ecs")->AsRecordType(); ::dns_edns_ecs = zeek::id::find_type("dns_edns_ecs")->AsRecordType();
::dns_edns_tcp_keepalive = zeek::id::find_type("dns_edns_tcp_keepalive")->AsRecordType(); ::dns_edns_tcp_keepalive = zeek::id::find_type("dns_edns_tcp_keepalive")->AsRecordType();
::dns_edns_cookie = zeek::id::find_type("dns_edns_cookie")->AsRecordType();
::dns_tsig_additional = zeek::id::find_type("dns_tsig_additional")->AsRecordType(); ::dns_tsig_additional = zeek::id::find_type("dns_tsig_additional")->AsRecordType();
::dns_rrsig_rr = zeek::id::find_type("dns_rrsig_rr")->AsRecordType(); ::dns_rrsig_rr = zeek::id::find_type("dns_rrsig_rr")->AsRecordType();
::dns_dnskey_rr = zeek::id::find_type("dns_dnskey_rr")->AsRecordType(); ::dns_dnskey_rr = zeek::id::find_type("dns_dnskey_rr")->AsRecordType();