From bcdbca4bb9c6688ebeff2a1423cea0196ee94478 Mon Sep 17 00:00:00 2001 From: Joost Jansen Date: Fri, 2 Dec 2022 11:27:25 +0100 Subject: [PATCH] Added several events for detailed info on the SSH2 key init directions --- src/analyzer/protocol/ssh/events.bif | 79 ++++++++++++++++-- src/analyzer/protocol/ssh/ssh-analyzer.pac | 61 +++++++++++++- src/analyzer/protocol/ssh/ssh-protocol.pac | 22 ++--- .../out | 2 + .../out | 12 +++ testing/btest/Traces/ssh/reverse-ssh.pcap | Bin 0 -> 12374 bytes .../protocols/ssh/ssh-reverse-connection.zeek | 12 +++ .../protocols/ssh/ssh_dh_gex_direction.zeek | 8 ++ 8 files changed, 178 insertions(+), 18 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.ssh.ssh-reverse-connection/out create mode 100644 testing/btest/Baseline/scripts.base.protocols.ssh.ssh_dh_gex_direction/out create mode 100644 testing/btest/Traces/ssh/reverse-ssh.pcap create mode 100644 testing/btest/scripts/base/protocols/ssh/ssh-reverse-connection.zeek create mode 100644 testing/btest/scripts/base/protocols/ssh/ssh_dh_gex_direction.zeek diff --git a/src/analyzer/protocol/ssh/events.bif b/src/analyzer/protocol/ssh/events.bif index 451f445e89..3b213749b2 100644 --- a/src/analyzer/protocol/ssh/events.bif +++ b/src/analyzer/protocol/ssh/events.bif @@ -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%); diff --git a/src/analyzer/protocol/ssh/ssh-analyzer.pac b/src/analyzer/protocol/ssh/ssh-analyzer.pac index dc1eba0b46..b93402ce31 100644 --- a/src/analyzer/protocol/ssh/ssh-analyzer.pac +++ b/src/analyzer/protocol/ssh/ssh-analyzer.pac @@ -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 { diff --git a/src/analyzer/protocol/ssh/ssh-protocol.pac b/src/analyzer/protocol/ssh/ssh-protocol.pac index a8c8328ef0..5a770e4af5 100644 --- a/src/analyzer/protocol/ssh/ssh-protocol.pac +++ b/src/analyzer/protocol/ssh/ssh-protocol.pac @@ -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; diff --git a/testing/btest/Baseline/scripts.base.protocols.ssh.ssh-reverse-connection/out b/testing/btest/Baseline/scripts.base.protocols.ssh.ssh-reverse-connection/out new file mode 100644 index 0000000000..b6a85318da --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ssh.ssh-reverse-connection/out @@ -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 diff --git a/testing/btest/Baseline/scripts.base.protocols.ssh.ssh_dh_gex_direction/out b/testing/btest/Baseline/scripts.base.protocols.ssh.ssh_dh_gex_direction/out new file mode 100644 index 0000000000..2ce9abb3bf --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ssh.ssh_dh_gex_direction/out @@ -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 diff --git a/testing/btest/Traces/ssh/reverse-ssh.pcap b/testing/btest/Traces/ssh/reverse-ssh.pcap new file mode 100644 index 0000000000000000000000000000000000000000..8ddc4acc1a0151cb6eff4f9758cb4b92adf4017b GIT binary patch literal 12374 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 +# @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"); + } +} diff --git a/testing/btest/scripts/base/protocols/ssh/ssh_dh_gex_direction.zeek b/testing/btest/scripts/base/protocols/ssh/ssh_dh_gex_direction.zeek new file mode 100644 index 0000000000..4b04335ee7 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ssh/ssh_dh_gex_direction.zeek @@ -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"); +}