Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/topic/jsiwek/gh-1264-ssh-host-ke…
Browse files Browse the repository at this point in the history
…y-fingerprints' into master

* origin/topic/jsiwek/gh-1264-ssh-host-key-fingerprints:
  Simply ssh/main.zeek by using "ssh_server_host_key" for fingerprinting
  Deprecate "ssh1_server_host_key" parameters *e* and *p*
  GH-1264: Implement "ssh_server_host_key" event
  • Loading branch information
jsiwek committed Nov 16, 2020
2 parents 50a49ea + 331b94d commit 02c0b33
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 43 deletions.
14 changes: 14 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@

3.3.0-dev.541 | 2020-11-16 11:22:00 -0800

* Simplify ssh/main.zeek by using "ssh_server_host_key" for fingerprinting (Jon Siwek, Corelight)

* Deprecate "ssh1_server_host_key" parameters *e* and *p* (Jon Siwek, Corelight)

They are named such that *e* is actually the modulus, not the exponent.
The replacement parameters are named *exponent* and *modulus* for
clarity.

* GH-1264: Implement "ssh_server_host_key" event (Jon Siwek, Corelight)

This event provides host key fingerprints for both SSH1 and SSH2.

3.3.0-dev.537 | 2020-11-16 11:03:05 +0000

* [SSH] Handle SSH version 1.99
Expand Down
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ Deprecated Functionality
- ``Type::GetAliases()`` and ``Type::AddAlias()`` are deprecated, use
``Type::Aliases()`` and ``Type::RegisterAlias()``.

- The ``ssh1_server_host_key`` event's modulus and exponent parameters,
*e* and *p*, were named in misleading way (*e* is the modulus)
and now deprecated in favor of the new *modulus* and *exponent* parameters.

Zeek 3.2.0
==========

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.3.0-dev.537
3.3.0-dev.541
3 changes: 2 additions & 1 deletion scripts/base/frameworks/intel/main.zeek
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export {
USER_NAME,
## Certificate SHA-1 hash.
CERT_HASH,
## Public key MD5 hash. (SSH server host keys are a good example.)
## Public key MD5 hash, formatted as hexadecimal digits delimited by colons.
## (SSH server host keys are a good example.)
PUBKEY_HASH,
};

Expand Down
29 changes: 3 additions & 26 deletions scripts/base/protocols/ssh/main.zeek
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,6 @@ export {
## ssh_server_host_key ssh_encrypted_packet ssh2_dh_server_params
## ssh2_gss_error ssh2_ecc_key
global ssh_auth_result: event(c: connection, result: bool, auth_attempts: count);

## Event that can be handled when the analyzer sees an SSH server host
## key. This abstracts :zeek:id:`ssh1_server_host_key` and
## :zeek:id:`ssh2_server_host_key`.
##
## .. zeek:see:: ssh_server_version ssh_client_version
## ssh_auth_successful ssh_auth_failed ssh_auth_result
## ssh_auth_attempted ssh_capabilities ssh2_server_host_key
## ssh1_server_host_key ssh_encrypted_packet ssh2_dh_server_params
## ssh2_gss_error ssh2_ecc_key
global ssh_server_host_key: event(c: connection, hash: string);
}

module SSH;
Expand Down Expand Up @@ -337,24 +326,12 @@ event ssh_auth_failed(c: connection) &priority=-5
event ssh_auth_result(c, F, c$ssh$auth_attempts);
}


function generate_fingerprint(c: connection, key: string)
event ssh_server_host_key(c: connection, hash: string) &priority=5
{
if ( !c?$ssh )
if ( ! c?$ssh )
return;

local lx = str_split_indices(md5_hash(key), vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30));
c$ssh$host_key = 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);
c$ssh$host_key = hash;
}

event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=20
Expand Down
44 changes: 41 additions & 3 deletions src/analyzer/protocol/ssh/events.bif
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,54 @@ event ssh2_server_host_key%(c: connection, key: string%);
## c: The connection over which the :abbr:`SSH (Secure Shell)`
## connection took place.
##
## p: The prime for the server's public host key.
## p: The exponent for the server's public host key (note this parameter
## is truly the exponent even though named *p* and the *exponent* parameter
## will eventually replace it).
##
## e: The exponent for the serer's public host key.
## e: The prime modulus for the server's public host key (note this parameter
## is truly the modulus even though named *e* and the *modulus* parameter
## will eventually replace it).
##
## modulus: The prime modulus of the server's public host key.
##
## exponent: The exponent of the server's public host key.
##
## .. zeek:see:: ssh_server_version ssh_client_version
## ssh_auth_successful ssh_auth_failed ssh_auth_result
## ssh_auth_attempted ssh_capabilities ssh2_server_host_key
## ssh_server_host_key ssh_encrypted_packet ssh2_dh_server_params
## ssh2_gss_error ssh2_ecc_key
event ssh1_server_host_key%(c: connection, p: string, e: string%);
event ssh1_server_host_key%(c: connection, p: string &deprecated="Remove in v4.1", e: string &deprecated="Remove in v4.1", modulus: string, exponent: string%);
event ssh1_server_host_key%(c: connection, modulus: string, exponent: string%);
event ssh1_server_host_key%(c: connection, p: string, e: string%) &deprecated="Remove in v4.1. The 'p' and 'e' parameters are misleadingly named don't use them.";

## During the :abbr:`SSH (Secure Shell)` key exchange, the server
## supplies its public host key. This event is generated when the
## appropriate key exchange message is seen for SSH1 or SSH2 and provides
## a fingerprint of the server's host key.
##
## c: The connection over which the :abbr:`SSH (Secure Shell)`
## connection took place.
##
## hash: an MD5 hash fingerprint associated with the server's host key.
## For SSH2, this is the hash of the "server public host key" string as
## seen on the wire in the Diffie-Hellman key exchange reply message
## (the string itself, excluding the 4-byte length associated with it),
## which is also the *key* parameter of :zeek:see:`ssh2_server_host_key`
## For SSH1, this is the hash of the combined multiprecision integer
## strings representing the RSA1 key's prime modulus and public exponent
## (concatenated in that order) as seen on the wire,
## which are also the parameters of :zeek:see:`ssh1_server_host_key`.
## In either case, the hash is the same "fingerprint" string as presented
## by other traditional tools, ``ssh``, ``ssh-keygen``, etc, and is the
## hexadecimal representation of all 16 MD5 hash bytes delimited by colons.
##
## .. zeek:see:: ssh_server_version ssh_client_version
## ssh_auth_successful ssh_auth_failed ssh_auth_result
## ssh_auth_attempted ssh_capabilities ssh2_server_host_key
## ssh1_server_host_key ssh_encrypted_packet ssh2_dh_server_params
## ssh2_gss_error ssh2_ecc_key
event ssh_server_host_key%(c: connection, hash: string%);
## This event is generated when an :abbr:`SSH (Secure Shell)`
## encrypted packet is seen. This event is not handled by default, but
Expand Down
46 changes: 42 additions & 4 deletions src/analyzer/protocol/ssh/ssh-analyzer.pac
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
#include <cstdlib>
#include <vector>
#include <string>
#include "zeek/digest.h"
%}

%header{
zeek::VectorValPtr name_list_to_vector(const bytestring& nl);
const char* fingerprint_md5(const unsigned char* d);
%}

%code{
Expand Down Expand Up @@ -45,6 +47,14 @@ zeek::VectorValPtr name_list_to_vector(const bytestring& nl)
}
return vv;
}

const char* fingerprint_md5(const unsigned char* d)
{
return zeek::util::fmt("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
}
%}

refine flow SSH_Flow += {
Expand Down Expand Up @@ -147,24 +157,52 @@ refine flow SSH_Flow += {

function proc_ssh2_server_host_key(key: bytestring): bool
%{
if ( ssh_server_host_key )
{
unsigned char digest[MD5_DIGEST_LENGTH];
zeek::detail::internal_md5(${key}.data(), ${key}.length(), digest);

zeek::BifEvent::enqueue_ssh_server_host_key(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
zeek::make_intrusive<zeek::StringVal>(fingerprint_md5(digest)));
}

if ( ssh2_server_host_key )
{
zeek::BifEvent::enqueue_ssh2_server_host_key(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
to_stringval(${key}));
}

return true;
%}

function proc_ssh1_server_host_key(p: bytestring, e: bytestring): bool
function proc_ssh1_server_host_key(exp: bytestring, mod: bytestring): bool
%{
if ( ssh_server_host_key )
{
unsigned char digest[MD5_DIGEST_LENGTH];
auto ctx = zeek::detail::hash_init(zeek::detail::Hash_MD5);
// Fingerprint is calculated over concatenation of modulus + exponent.
zeek::detail::hash_update(ctx, ${mod}.data(), ${mod}.length());
zeek::detail::hash_update(ctx, ${exp}.data(), ${exp}.length());
zeek::detail::hash_final(ctx, digest);

zeek::BifEvent::enqueue_ssh_server_host_key(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
zeek::make_intrusive<zeek::StringVal>(fingerprint_md5(digest)));
}

if ( ssh1_server_host_key )
{
zeek::BifEvent::enqueue_ssh1_server_host_key(connection()->zeek_analyzer(),
connection()->zeek_analyzer()->Conn(),
to_stringval(${p}),
to_stringval(${e}));
to_stringval(${exp}),
to_stringval(${mod}),
to_stringval(${mod}),
to_stringval(${exp}));
}

return true;
%}

Expand Down Expand Up @@ -229,5 +267,5 @@ refine typeattr SSH2_ECC_INIT += &let {
};

refine typeattr SSH1_PUBLIC_KEY += &let {
proc: bool = $context.flow.proc_ssh1_server_host_key(host_key_p.val, host_key_e.val);
proc: bool = $context.flow.proc_ssh1_server_host_key(host_key_exp.val, host_key_mod.val);
};
8 changes: 4 additions & 4 deletions src/analyzer/protocol/ssh/ssh-protocol.pac
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ type SSH1_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_typ
type SSH1_PUBLIC_KEY(length: uint32) = record {
cookie : bytestring &length=8;
server_key : uint32;
server_key_p : ssh1_mp_int;
server_key_e : ssh1_mp_int;
server_key_exp : ssh1_mp_int;
server_key_mod : ssh1_mp_int;
host_key : uint32;
host_key_p : ssh1_mp_int;
host_key_e : ssh1_mp_int;
host_key_exp : ssh1_mp_int;
host_key_mod : ssh1_mp_int;
flags : uint32;
supported_ciphers : uint32;
supported_auths : uint32;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path reporter
#open 2020-09-24-00-19-13
#open XXXX-XX-XX-XX-XX-XX
#fields ts level message location
#types time enum string string
1600906753.185591 Reporter::INFO Tried to remove non-existing item '192.168.1.1' (Intel::ADDR). /home/christian/devel/zeek/zeek/scripts/base/frameworks/intel/./main.zeek, lines 565-566
1600906753.185591 Reporter::INFO received termination signal (empty)
#close 2020-09-24-00-19-13
XXXXXXXXXX.XXXXXX Reporter::INFO Tried to remove non-existing item '192.168.1.1' (Intel::ADDR). <...>/main.zeek, lines 566-567
XXXXXXXXXX.XXXXXX Reporter::INFO received termination signal (empty)
#close XXXX-XX-XX-XX-XX-XX
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
ssh server host key fingerprint, c7:eb:77:5d:d1:64:31:d6:1b:e8:99:5f:a7:09:a1:d7
ssh2 server host key fingerprint, c7eb775dd16431d61be8995fa709a1d7
ssh server host key fingerprint, 55:17:eb:fa:2e:7f:b3:7b:33:42:7c:9d:44:85:56:da
ssh1 server host key fingerprint, 5517ebfa2e7fb37b33427c9d448556da
Binary file not shown.
19 changes: 19 additions & 0 deletions testing/btest/scripts/base/protocols/ssh/fingerprints.zeek
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# @TEST-EXEC: zeek -r $TRACES/ssh/ssh1-ssh2-fingerprints.pcap %INPUT >out
# @TEST-EXEC: btest-diff out

@load base/protocols/ssh

event ssh2_server_host_key(c: connection, key: string)
{
print "ssh2 server host key fingerprint", md5_hash(key);
}

event ssh1_server_host_key(c: connection, modulus: string, exponent: string)
{
print "ssh1 server host key fingerprint", md5_hash(modulus + exponent);
}

event ssh_server_host_key(c: connection, hash: string)
{
print "ssh server host key fingerprint", hash;
}

0 comments on commit 02c0b33

Please sign in to comment.