mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
GH-1264: Implement "ssh_server_host_key" event
This event provides host key fingerprints for both SSH1 and SSH2.
This commit is contained in:
parent
93469d811d
commit
bd40a97a78
8 changed files with 97 additions and 16 deletions
|
@ -30,7 +30,8 @@ export {
|
||||||
USER_NAME,
|
USER_NAME,
|
||||||
## Certificate SHA-1 hash.
|
## Certificate SHA-1 hash.
|
||||||
CERT_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,
|
PUBKEY_HASH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -111,17 +111,6 @@ export {
|
||||||
## ssh_server_host_key ssh_encrypted_packet ssh2_dh_server_params
|
## ssh_server_host_key ssh_encrypted_packet ssh2_dh_server_params
|
||||||
## ssh2_gss_error ssh2_ecc_key
|
## ssh2_gss_error ssh2_ecc_key
|
||||||
global ssh_auth_result: event(c: connection, result: bool, auth_attempts: count);
|
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;
|
module SSH;
|
||||||
|
|
|
@ -138,6 +138,34 @@ event ssh2_server_host_key%(c: connection, key: string%);
|
||||||
## ssh2_gss_error ssh2_ecc_key
|
## 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, e: string%);
|
||||||
|
|
||||||
|
## 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)`
|
## This event is generated when an :abbr:`SSH (Secure Shell)`
|
||||||
## encrypted packet is seen. This event is not handled by default, but
|
## encrypted packet is seen. This event is not handled by default, but
|
||||||
## is provided for heuristic analysis scripts. Note that you have to set
|
## is provided for heuristic analysis scripts. Note that you have to set
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "zeek/digest.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%header{
|
%header{
|
||||||
zeek::VectorValPtr name_list_to_vector(const bytestring& nl);
|
zeek::VectorValPtr name_list_to_vector(const bytestring& nl);
|
||||||
|
const char* fingerprint_md5(const unsigned char* d);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%code{
|
%code{
|
||||||
|
@ -45,6 +47,14 @@ zeek::VectorValPtr name_list_to_vector(const bytestring& nl)
|
||||||
}
|
}
|
||||||
return vv;
|
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 += {
|
refine flow SSH_Flow += {
|
||||||
|
@ -153,6 +163,17 @@ refine flow SSH_Flow += {
|
||||||
connection()->zeek_analyzer()->Conn(),
|
connection()->zeek_analyzer()->Conn(),
|
||||||
to_stringval(${key}));
|
to_stringval(${key}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -165,6 +186,23 @@ refine flow SSH_Flow += {
|
||||||
to_stringval(${p}),
|
to_stringval(${p}),
|
||||||
to_stringval(${e}));
|
to_stringval(${e}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ssh_server_host_key )
|
||||||
|
{
|
||||||
|
unsigned char digest[MD5_DIGEST_LENGTH];
|
||||||
|
auto ctx = zeek::detail::hash_init(zeek::detail::Hash_MD5);
|
||||||
|
// Note: the 'p' and 'e' parameters actually have swapped meanings with
|
||||||
|
// 'p' actually being the exponent.
|
||||||
|
// Fingerprint is calculated over concatenation of modulus + exponent.
|
||||||
|
zeek::detail::hash_update(ctx, ${e}.data(), ${e}.length());
|
||||||
|
zeek::detail::hash_update(ctx, ${p}.data(), ${p}.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)));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -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
|
#separator \x09
|
||||||
#set_separator ,
|
#set_separator ,
|
||||||
#empty_field (empty)
|
#empty_field (empty)
|
||||||
#unset_field -
|
#unset_field -
|
||||||
#path reporter
|
#path reporter
|
||||||
#open 2020-09-24-00-19-13
|
#open XXXX-XX-XX-XX-XX-XX
|
||||||
#fields ts level message location
|
#fields ts level message location
|
||||||
#types time enum string string
|
#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
|
XXXXXXXXXX.XXXXXX Reporter::INFO Tried to remove non-existing item '192.168.1.1' (Intel::ADDR). <...>/main.zeek, lines 566-567
|
||||||
1600906753.185591 Reporter::INFO received termination signal (empty)
|
XXXXXXXXXX.XXXXXX Reporter::INFO received termination signal (empty)
|
||||||
#close 2020-09-24-00-19-13
|
#close XXXX-XX-XX-XX-XX-XX
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
ssh2 server host key fingerprint, c7eb775dd16431d61be8995fa709a1d7
|
||||||
|
ssh server host key fingerprint, c7:eb:77:5d:d1:64:31:d6:1b:e8:99:5f:a7:09:a1:d7
|
||||||
|
ssh1 server host key fingerprint, 5517ebfa2e7fb37b33427c9d448556da
|
||||||
|
ssh server host key fingerprint, 55:17:eb:fa:2e:7f:b3:7b:33:42:7c:9d:44:85:56:da
|
BIN
testing/btest/Traces/ssh/ssh1-ssh2-fingerprints.pcap
Normal file
BIN
testing/btest/Traces/ssh/ssh1-ssh2-fingerprints.pcap
Normal file
Binary file not shown.
19
testing/btest/scripts/base/protocols/ssh/fingerprints.zeek
Normal file
19
testing/btest/scripts/base/protocols/ssh/fingerprints.zeek
Normal file
|
@ -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, p: string, e: string)
|
||||||
|
{
|
||||||
|
print "ssh1 server host key fingerprint", md5_hash(e + p);
|
||||||
|
}
|
||||||
|
|
||||||
|
event ssh_server_host_key(c: connection, hash: string)
|
||||||
|
{
|
||||||
|
print "ssh server host key fingerprint", hash;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue