From 2cd2c65fe37669218b1131d253574afcfe79c7a6 Mon Sep 17 00:00:00 2001 From: Mauro Palumbo Date: Thu, 6 Jun 2019 16:38:05 +0200 Subject: [PATCH] fix auth field (key_id and mac) in standard and control msg --- scripts/base/init-bare.zeek | 63 +++------------------- scripts/base/protocols/ntp/main.zeek | 24 ++++++--- src/analyzer/protocol/ntp/ntp-analyzer.pac | 10 ++-- src/analyzer/protocol/ntp/ntp-protocol.pac | 32 ++++++----- 4 files changed, 51 insertions(+), 78 deletions(-) diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 42e0eea538..884fa1f738 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -2526,54 +2526,6 @@ export { }; } -module NTP; - -export { - ## NTP message as defined in :rfc:`5905`. - ## Doesn't include fields for mode 7 (reserved for private use), e.g. monlist - type NTP::Message: record { - ## The NTP version number - version: count; - ## The NTP mode being used - mode: count; - ## The stratum (primary server, secondary server, etc.) - stratum: count; - ## The maximum interval between successive messages - poll: interval; - ## The precision of the system clock - precision: interval; - - ## Total round-trip delay to the reference clock - root_delay: interval; - ## Total dispersion to the reference clock - root_disp: interval; - ## For stratum 0, 4 character string used for debugging - kiss_code: string &optional; - ## For stratum 1, ID assigned to the reference clock by IANA - ref_id: string &optional; - ## Above stratum 1, when using IPv4, the IP address of the reference clock - ref_addr: addr &optional; - - ## Above stratum 1, when using IPv6, the first four bytes of the MD5 hash of the - ## IPv6 address of the reference clock - ref_v6_hash_prefix: string &optional; - ## Time when the system clock was last set or correct - ref_time: time; - ## Time at the client when the request departed for the NTP server - org_time: time; - ## Time at the server when the request arrived from the NTP client - rec_time: time; - ## Time at the server when the response departed for the NTP client - xmt_time: time; - ## Key used to designate a secret MD5 key - key_id: count &optional; - ## MD5 hash computed over the key followed by the NTP packet header and extension fields - digest: string &optional; - ## Number of extension fields (which are not currently parsed) - num_exts: count &default=0; - }; -} - module NTLM; @@ -5045,15 +4997,16 @@ export { ## The sequence number of the command or response sequence : count; ## The current status of the system, peer or clock - status : count; #TODO: this must be further specified + status : count; #TODO: this can be further parsed internally ## A 16-bit integer identifying a valid association association_id : count; - ## A 16-bit integer indicating the offset, in octets, of the first octet in the data area - offs : count; - ## A 16-bit integer indicating the length of the data field, in octets - c : count; ## The message data for the command or response + Authenticator (optional) - data : string &optional; # TODO: distinguish data and authenticator + data : string &optional; + ## This is an integer identifying the cryptographic + ## key used to generate the message-authentication code + key_id : count &optional; + ## This is a crypto-checksum computed by the encryption procedure + crypto_checksum : string &optional; }; ## NTP mode7 message for mode=7. Note that this is not defined in any RFC @@ -5095,7 +5048,7 @@ export { ## 7 - authentication failure (i.e. permission denied) err : count; ## Rest of data - data : string &optional; # TODO: can be further parsed + data : string &optional; }; ## NTP message as defined in :rfc:`5905`. diff --git a/scripts/base/protocols/ntp/main.zeek b/scripts/base/protocols/ntp/main.zeek index de65863c39..40b2b9caf0 100644 --- a/scripts/base/protocols/ntp/main.zeek +++ b/scripts/base/protocols/ntp/main.zeek @@ -76,6 +76,12 @@ export { status : count &log; ## A 16-bit integer identifying a valid association association_id : count &log; + ## This is an integer identifying the cryptographic + ## key used to generate the message-authentication code + ctrl_key_id : count &optional &log; + ## This is a crypto-checksum computed by the encryption procedure + crypto_checksum : string &optional &log; + ## An implementation-specific code which specifies the ## operation to be (which has been) performed and/or the @@ -133,13 +139,13 @@ event ntp_message(c: connection, is_orig: bool, msg: NTP::Message) &priority=5 info$root_delay = msg$std_msg$root_delay; info$root_disp = msg$std_msg$root_disp; - if ( info?$kiss_code) + if ( msg$std_msg?$kiss_code) info$kiss_code = msg$std_msg$kiss_code; - if ( info?$ref_id) + if ( msg$std_msg?$ref_id) info$ref_id = msg$std_msg$ref_id; - if ( info?$ref_addr) + if ( msg$std_msg?$ref_addr) info$ref_addr = msg$std_msg$ref_addr; - if ( info?$ref_v6_hash_prefix) + if ( msg$std_msg?$ref_v6_hash_prefix) info$ref_v6_hash_prefix = msg$std_msg$ref_v6_hash_prefix; info$ref_time = msg$std_msg$ref_time; @@ -147,9 +153,9 @@ event ntp_message(c: connection, is_orig: bool, msg: NTP::Message) &priority=5 info$rec_time = msg$std_msg$rec_time; info$xmt_time = msg$std_msg$xmt_time; - if ( info?$key_id) + if ( msg$std_msg?$key_id) info$key_id = msg$std_msg$key_id; - if ( info?$digest) + if ( msg$std_msg?$digest) info$digest = msg$std_msg$digest; info$num_exts = msg$std_msg$num_exts; @@ -163,6 +169,12 @@ event ntp_message(c: connection, is_orig: bool, msg: NTP::Message) &priority=5 info$sequence = msg$control_msg$sequence; info$status = msg$control_msg$status; info$association_id = msg$control_msg$association_id; + + if ( msg$control_msg?$key_id) + info$ctrl_key_id = msg$control_msg$key_id; + if ( msg$control_msg?$crypto_checksum) + info$crypto_checksum = msg$control_msg$crypto_checksum; + } if ( msg$mode==7 ) { diff --git a/src/analyzer/protocol/ntp/ntp-analyzer.pac b/src/analyzer/protocol/ntp/ntp-analyzer.pac index 8ab14bb0bf..af42ddf9d1 100644 --- a/src/analyzer/protocol/ntp/ntp-analyzer.pac +++ b/src/analyzer/protocol/ntp/ntp-analyzer.pac @@ -65,12 +65,12 @@ refine flow NTP_Flow += { rv->Assign(11, proc_ntp_timestamp(${nsm.receive_ts})); rv->Assign(12, proc_ntp_timestamp(${nsm.transmit_ts})); - if (${nsm.mac.key_id}) { - //rv->Assign(13, val_mgr->GetCount(${nsm.mac.key_id})); - //rv->Assign(14, bytestring_to_val(${nsm.mac.digest})); - cout<<"booo"<Assign(13, val_mgr->GetCount(${nsm.mac.key_id})); + rv->Assign(14, bytestring_to_val(${nsm.mac.digest})); } - rv->Assign(15, val_mgr->GetCount((uint32) ${nsm.extensions}->size())); + // TODO: add extension fields + //rv->Assign(15, val_mgr->GetCount((uint32) ${nsm.extensions}->size())); return rv; %} diff --git a/src/analyzer/protocol/ntp/ntp-protocol.pac b/src/analyzer/protocol/ntp/ntp-protocol.pac index 721780c261..fd3a43f9c9 100644 --- a/src/analyzer/protocol/ntp/ntp-protocol.pac +++ b/src/analyzer/protocol/ntp/ntp-protocol.pac @@ -39,13 +39,14 @@ type NTP_std_msg = record { origin_ts : NTP_Time; receive_ts : NTP_Time; transmit_ts : NTP_Time; - extensions : Extension_Field[] &until($input.length() <= 18); - have_mac : case (offsetof(have_mac) < length) of { + #extensions : Extension_Field[] &until($input.length() == 20); #TODO: this need to be properly parsed + mac_fields : case (has_mac) of { true -> mac : NTP_MAC; false -> nil : empty; - } &requires(length); + } &requires(has_mac); } &let { length = sourcedata.length(); + has_mac: bool = (length - offsetof(mac_fields)) == 20; } &byteorder=bigendian &exportsourcedata; # This format is for mode==6, control msg @@ -53,33 +54,40 @@ type NTP_std_msg = record { type NTP_control_msg = record { second_byte : uint8; sequence : uint16; - status : uint16; #TODO: this must be further specified + status : uint16; #TODO: this can be further parsed internally association_id : uint16; offs : uint16; c : uint16; data : bytestring &length=c; - have_mac : case (offsetof(have_mac) < length) of { - true -> mac : NTP_MAC; + mac_fields : case (has_control_mac) of { + true -> mac : NTP_CONTROL_MAC; false -> nil : empty; - } &requires(length); + } &requires(has_control_mac); } &let { R: bool = (second_byte & 0x80) > 0; # First bit of 8-bits value E: bool = (second_byte & 0x40) > 0; # Second bit of 8-bits value M: bool = (second_byte & 0x20) > 0; # Third bit of 8-bits value - OpCode: uint8 = (second_byte & 0x1F); # Last 5 bits of 8-bits value + OpCode: uint8 = (second_byte & 0x1F); # Last 5 bits of 8-bits value length = sourcedata.length(); + has_control_mac: bool = (length - offsetof(mac_fields)) == 12; } &byteorder=bigendian &exportsourcedata; - +# As in RFC 5905 type NTP_MAC = record { key_id: uint32; digest: bytestring &length=16; -} &length=18; +} &length=20; + +# As in RFC 1119 +type NTP_CONTROL_MAC = record { + key_id: uint32; + crypto_checksum: bytestring &length=8; +} &length=12; type Extension_Field = record { field_type: uint16; - length : uint16; - data : bytestring &length=length-4; + ext_len : uint16; + data : bytestring &length=ext_len-4; }; type NTP_Short_Time = record {