mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Added several events for detailed info on the SSH2 key init directions
This commit is contained in:
parent
dbbb6cd6f0
commit
bcdbca4bb9
8 changed files with 178 additions and 18 deletions
|
@ -100,7 +100,8 @@ event ssh_auth_attempted%(c: connection, authenticated: bool%);
|
|||
## ssh_auth_successful ssh_auth_failed ssh_auth_result
|
||||
## ssh_auth_attempted ssh2_server_host_key ssh1_server_host_key
|
||||
## ssh_server_host_key ssh_encrypted_packet ssh2_dh_server_params
|
||||
## ssh2_gss_error ssh2_ecc_key
|
||||
## ssh2_gss_error ssh2_ecc_key ssh2_ecc_init ssh2_dh_gex_init
|
||||
## ssh2_rsa_secret ssh2_gss_init
|
||||
event ssh_capabilities%(c: connection, cookie: string, capabilities: SSH::Capabilities%);
|
||||
|
||||
## During the :abbr:`SSH (Secure Shell)` key exchange, the server
|
||||
|
@ -171,7 +172,8 @@ event ssh1_server_host_key%(c: connection, modulus: string, exponent: string%);
|
|||
## 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
|
||||
## ssh2_gss_error ssh2_ecc_key ssh2_ecc_init ssh2_dh_gex_init
|
||||
## ssh2_gss_init ssh2_rsa_secret
|
||||
event ssh_server_host_key%(c: connection, hash: string%);
|
||||
|
||||
## This event is generated when an :abbr:`SSH (Secure Shell)`
|
||||
|
@ -211,7 +213,7 @@ event ssh_encrypted_packet%(c: connection, orig: bool, len: count%);
|
|||
## ssh_auth_successful ssh_auth_failed ssh_auth_result
|
||||
## ssh_auth_attempted ssh_capabilities ssh2_server_host_key
|
||||
## ssh1_server_host_key ssh_server_host_key ssh_encrypted_packet
|
||||
## ssh2_gss_error ssh2_ecc_key
|
||||
## ssh2_gss_error ssh2_dh_gex_init
|
||||
event ssh2_dh_server_params%(c: connection, p: string, q: string%);
|
||||
|
||||
## In the event of a GSS-API error on the server, the server MAY send
|
||||
|
@ -231,7 +233,7 @@ event ssh2_dh_server_params%(c: connection, p: string, q: string%);
|
|||
## ssh_auth_successful ssh_auth_failed ssh_auth_result
|
||||
## ssh_auth_attempted ssh_capabilities ssh2_server_host_key
|
||||
## ssh1_server_host_key ssh_server_host_key ssh_encrypted_packet
|
||||
## ssh2_dh_server_params ssh2_ecc_key
|
||||
## ssh2_dh_server_params ssh2_ecc_key ssh2_gss_init
|
||||
event ssh2_gss_error%(c: connection, major_status: count, minor_status: count, err_msg: string%);
|
||||
|
||||
## The :abbr:`ECDH (Elliptic Curve Diffie-Hellman)` and
|
||||
|
@ -251,5 +253,72 @@ event ssh2_gss_error%(c: connection, major_status: count, minor_status: count, e
|
|||
## ssh_auth_successful ssh_auth_failed ssh_auth_result
|
||||
## ssh_auth_attempted ssh_capabilities ssh2_server_host_key
|
||||
## ssh1_server_host_key ssh_server_host_key ssh_encrypted_packet
|
||||
## ssh2_dh_server_params ssh2_gss_error
|
||||
## ssh2_dh_server_params ssh2_gss_error ssh2_ecc_init
|
||||
event ssh2_ecc_key%(c: connection, is_orig: bool, q: string%);
|
||||
|
||||
## The :abbr:`ECDH (Elliptic Curve Diffie-Hellman)` and
|
||||
## :abbr:`ECMQV (Elliptic Curve Menezes-Qu-Vanstone)` key exchange
|
||||
## algorithms use two ephemeral key pairs to generate a shared
|
||||
## secret. This event is generated when either the SSH_MSG_KEX_ECDH_INIT
|
||||
## or SSH_MSG_ECMQV_INIT message is observed. By definition, these need
|
||||
## to originate from the client and not from the server.
|
||||
## For more information, see:
|
||||
## :rfc:`5656#section-4`.
|
||||
##
|
||||
## c: The connection
|
||||
##
|
||||
## is_orig: Did this message come from the originator?
|
||||
##
|
||||
## .. 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_server_host_key ssh_encrypted_packet
|
||||
## ssh2_dh_server_params ssh2_gss_error ssh2_ecc_key
|
||||
event ssh2_ecc_init%(c: connection, is_orig: bool%);
|
||||
|
||||
## Generated if the connection uses a Diffie-Hellman Group Exchange
|
||||
## key exchange method. This event contains the direction of the key
|
||||
## exchange setup, which is indicated by the the SSH_MSG_KEX_DH_GEX_INIT
|
||||
## message as defined in :rfc:`4419#section-3`.
|
||||
##
|
||||
## c: The connection
|
||||
##
|
||||
## is_orig: Did this message come from the originator?
|
||||
##
|
||||
## .. 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_server_host_key ssh_encrypted_packet
|
||||
## ssh2_dh_server_params ssh2_gss_error
|
||||
event ssh2_dh_gex_init%(c: connection, is_orig: bool%);
|
||||
|
||||
## In the event of a GSS-API key exchange, this event is raised on
|
||||
## SSH_MSG_KEXGSS_INIT message.
|
||||
## For more information see :rfc:`4462#section-2.1`.
|
||||
##
|
||||
## c: The connection
|
||||
##
|
||||
## is_orig: Did this message come from the originator?
|
||||
##
|
||||
## .. 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_server_host_key ssh_encrypted_packet
|
||||
## ssh2_dh_server_params ssh2_gss_error
|
||||
event ssh2_gss_init%(c: connection, is_orig: bool%);
|
||||
|
||||
## In the event of a GSS-API key exchange, this event is raised on
|
||||
## SSH_MSG_KEXRSA_PUBKEY message. This message is sent first by the server,
|
||||
## after which the server will respond with a SSH_MSG_KEXRSA_SECRET message.
|
||||
## For more information see :rfc:`4432#section-4`.
|
||||
##
|
||||
## c: The connection
|
||||
##
|
||||
## is_orig: Did this message come from the originator?
|
||||
##
|
||||
## .. 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_server_host_key ssh_encrypted_packet
|
||||
## ssh2_dh_server_params ssh2_gss_error
|
||||
event ssh2_rsa_secret%(c: connection, is_orig: bool%);
|
||||
|
|
|
@ -120,6 +120,50 @@ refine flow SSH_Flow += {
|
|||
return true;
|
||||
%}
|
||||
|
||||
function proc_ssh2_ecc_init(is_orig: bool): bool
|
||||
%{
|
||||
if ( ssh2_ecc_init )
|
||||
{
|
||||
zeek::BifEvent::enqueue_ssh2_ecc_init(connection()->zeek_analyzer(),
|
||||
connection()->zeek_analyzer()->Conn(),
|
||||
is_orig);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_ssh2_dh_gex_init(is_orig: bool): bool
|
||||
%{
|
||||
if ( ssh2_dh_gex_init )
|
||||
{
|
||||
zeek::BifEvent::enqueue_ssh2_dh_gex_init(connection()->zeek_analyzer(),
|
||||
connection()->zeek_analyzer()->Conn(),
|
||||
is_orig);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
|
||||
function proc_ssh2_gss_init(is_orig: bool): bool
|
||||
%{
|
||||
if ( ssh2_gss_init )
|
||||
{
|
||||
zeek::BifEvent::enqueue_ssh2_gss_init(connection()->zeek_analyzer(),
|
||||
connection()->zeek_analyzer()->Conn(),
|
||||
is_orig);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_ssh2_rsa_secret(is_orig: bool): bool
|
||||
%{
|
||||
if ( ssh2_rsa_secret )
|
||||
{
|
||||
zeek::BifEvent::enqueue_ssh2_rsa_secret(connection()->zeek_analyzer(),
|
||||
connection()->zeek_analyzer()->Conn(),
|
||||
is_orig);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_ssh2_dh_gex_group(msg: SSH2_DH_GEX_GROUP): bool
|
||||
%{
|
||||
|
@ -257,11 +301,24 @@ refine typeattr SSH2_DH_GEX_GROUP += &let {
|
|||
|
||||
refine typeattr SSH2_ECC_REPLY += &let {
|
||||
proc_k: bool = $context.flow.proc_ssh2_server_host_key(k_s.val);
|
||||
proc_q: bool = $context.flow.proc_ssh2_ecc_key(q_s.val, false);
|
||||
proc_q: bool = $context.flow.proc_ssh2_ecc_key(q_s.val, is_orig);
|
||||
};
|
||||
|
||||
refine typeattr SSH2_ECC_INIT += &let {
|
||||
proc: bool = $context.flow.proc_ssh2_ecc_key(q_c.val, true);
|
||||
proc: bool = $context.flow.proc_ssh2_ecc_key(q_c.val, is_orig);
|
||||
proc_init: bool = $context.flow.proc_ssh2_ecc_init(is_orig);
|
||||
};
|
||||
|
||||
refine typeattr SSH2_DH_GEX_INIT += &let {
|
||||
proc_init: bool = $context.flow.proc_ssh2_dh_gex_init(is_orig);
|
||||
};
|
||||
|
||||
refine typeattr SSH2_GSS_INIT += &let {
|
||||
proc_init: bool = $context.flow.proc_ssh2_gss_init(is_orig);
|
||||
};
|
||||
|
||||
refine typeattr SSH2_RSA_SECRET += &let {
|
||||
proc_init: bool = $context.flow.proc_ssh2_rsa_secret(is_orig);
|
||||
};
|
||||
|
||||
refine typeattr SSH1_PUBLIC_KEY += &let {
|
||||
|
|
|
@ -130,7 +130,7 @@ type SSH2_KEXINIT(length: uint32, is_orig: bool) = record {
|
|||
# KEX_DH exchanges
|
||||
|
||||
type SSH2_Key_Exchange_DH_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_type of {
|
||||
SSH_MSG_KEXDH_INIT -> init : SSH2_DH_GEX_INIT(length);
|
||||
SSH_MSG_KEXDH_INIT -> init : SSH2_DH_GEX_INIT(length, is_orig);
|
||||
SSH_MSG_KEXDH_REPLY -> reply : SSH2_DH_GEX_REPLY(length);
|
||||
default -> unknown: bytestring &length=length &transient;
|
||||
};
|
||||
|
@ -141,7 +141,7 @@ type SSH2_Key_Exchange_DH_GEX_Message(is_orig: bool, msg_type: uint8, length: ui
|
|||
SSH_MSG_KEX_DH_GEX_REQUEST_OLD -> request_old : SSH2_DH_GEX_REQUEST_OLD;
|
||||
SSH_MSG_KEX_DH_GEX_REQUEST -> request : SSH2_DH_GEX_REQUEST;
|
||||
SSH_MSG_KEX_DH_GEX_GROUP -> group : SSH2_DH_GEX_GROUP(length);
|
||||
SSH_MSG_KEX_DH_GEX_INIT -> init : SSH2_DH_GEX_INIT(length);
|
||||
SSH_MSG_KEX_DH_GEX_INIT -> init : SSH2_DH_GEX_INIT(length, is_orig);
|
||||
SSH_MSG_KEX_DH_GEX_REPLY -> reply : SSH2_DH_GEX_REPLY(length);
|
||||
default -> unknown : bytestring &length=length &transient;
|
||||
};
|
||||
|
@ -161,7 +161,7 @@ type SSH2_DH_GEX_GROUP(length: uint32) = record {
|
|||
g : ssh_string;
|
||||
} &length=length;
|
||||
|
||||
type SSH2_DH_GEX_INIT(length: uint32) = record {
|
||||
type SSH2_DH_GEX_INIT(length: uint32, is_orig: bool) = record {
|
||||
e : ssh_string;
|
||||
} &length=length;
|
||||
|
||||
|
@ -175,7 +175,7 @@ type SSH2_DH_GEX_REPLY(length: uint32) = record {
|
|||
|
||||
type SSH2_Key_Exchange_RSA_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_type of {
|
||||
SSH_MSG_KEXRSA_PUBKEY -> pubkey : SSH2_RSA_PUBKEY(length);
|
||||
SSH_MSG_KEXRSA_SECRET -> secret : SSH2_RSA_SECRET(length);
|
||||
SSH_MSG_KEXRSA_SECRET -> secret : SSH2_RSA_SECRET(length, is_orig);
|
||||
SSH_MSG_KEXRSA_DONE -> done : SSH2_RSA_DONE(length);
|
||||
};
|
||||
|
||||
|
@ -184,7 +184,7 @@ type SSH2_RSA_PUBKEY(length: uint32) = record {
|
|||
k_t : ssh_string;
|
||||
} &length=length;
|
||||
|
||||
type SSH2_RSA_SECRET(length: uint32) = record {
|
||||
type SSH2_RSA_SECRET(length: uint32, is_orig: bool) = record {
|
||||
encrypted_payload : ssh_string;
|
||||
} &length=length;
|
||||
|
||||
|
@ -195,7 +195,7 @@ type SSH2_RSA_DONE(length: uint32) = record {
|
|||
# KEX_GSS exchanges
|
||||
|
||||
type SSH2_Key_Exchange_GSS_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_type of {
|
||||
SSH_MSG_KEXGSS_INIT -> init : SSH2_GSS_INIT(length);
|
||||
SSH_MSG_KEXGSS_INIT -> init : SSH2_GSS_INIT(length, is_orig);
|
||||
SSH_MSG_KEXGSS_CONTINUE -> cont : SSH2_GSS_CONTINUE(length);
|
||||
SSH_MSG_KEXGSS_COMPLETE -> complete : SSH2_GSS_COMPLETE(length);
|
||||
SSH_MSG_KEXGSS_HOSTKEY -> hostkey : SSH2_GSS_HOSTKEY(length);
|
||||
|
@ -204,7 +204,7 @@ type SSH2_Key_Exchange_GSS_Message(is_orig: bool, msg_type: uint8, length: uint3
|
|||
SSH_MSG_KEXGSS_GROUP -> group : SSH2_DH_GEX_GROUP(length);
|
||||
};
|
||||
|
||||
type SSH2_GSS_INIT(length: uint32) = record {
|
||||
type SSH2_GSS_INIT(length: uint32, is_orig: bool) = record {
|
||||
output_token : ssh_string;
|
||||
e : ssh_string;
|
||||
} &length=length;
|
||||
|
@ -237,19 +237,19 @@ type SSH2_GSS_ERROR(length: uint32) = record {
|
|||
# KEX_ECDH and KEX_ECMQV exchanges
|
||||
|
||||
type SSH2_Key_Exchange_ECC_Message(is_orig: bool, msg_type: uint8, length: uint32) = case msg_type of {
|
||||
SSH_MSG_KEX_ECDH_INIT -> init : SSH2_ECC_INIT(length);
|
||||
SSH_MSG_KEX_ECDH_REPLY -> reply : SSH2_ECC_REPLY(length);
|
||||
SSH_MSG_KEX_ECDH_INIT -> init : SSH2_ECC_INIT(length, is_orig);
|
||||
SSH_MSG_KEX_ECDH_REPLY -> reply : SSH2_ECC_REPLY(length, is_orig);
|
||||
};
|
||||
|
||||
# This deviates from the RFC. SSH_MSG_KEX_ECDH_INIT and
|
||||
# SSH_MSG_KEX_ECMQV_INIT can be parsed the same way.
|
||||
type SSH2_ECC_INIT(length: uint32) = record {
|
||||
type SSH2_ECC_INIT(length: uint32, is_orig: bool) = record {
|
||||
q_c : ssh_string;
|
||||
};
|
||||
|
||||
# This deviates from the RFC. SSH_MSG_KEX_ECDH_REPLY and
|
||||
# SSH_MSG_KEX_ECMQV_REPLY can be parsed the same way.
|
||||
type SSH2_ECC_REPLY(length: uint32) = record {
|
||||
type SSH2_ECC_REPLY(length: uint32, is_orig: bool) = record {
|
||||
k_s : ssh_string;
|
||||
q_s : ssh_string;
|
||||
signature : ssh_string;
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||
Detected an ECC INIT not from the TCP client
|
|
@ -0,0 +1,12 @@
|
|||
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
||||
Found SSH2_DH_GEX_INIT event
|
BIN
testing/btest/Traces/ssh/reverse-ssh.pcap
Normal file
BIN
testing/btest/Traces/ssh/reverse-ssh.pcap
Normal file
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
# @TEST-EXEC: zeek -b -Cr $TRACES/ssh/reverse-ssh.pcap %INPUT >out
|
||||
# @TEST-EXEC: btest-diff out
|
||||
|
||||
@load base/protocols/ssh
|
||||
|
||||
event ssh2_ecc_init(c: connection, is_orig: bool) {
|
||||
## If a machine sends out the initial key material for the handshake, this should come from the client.
|
||||
## In most cases, this client is the machine that set up the TCP connection.
|
||||
if ( ! is_orig ) {
|
||||
print("Detected an ECC INIT not from the TCP client");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# @TEST-EXEC: zeek -b -Cr $TRACES/ssh/sshguess.pcap %INPUT >out
|
||||
# @TEST-EXEC: btest-diff out
|
||||
|
||||
@load base/protocols/ssh
|
||||
|
||||
event ssh2_dh_gex_init(c: connection, is_orig: bool) {
|
||||
print("Found SSH2_DH_GEX_INIT event");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue