diff --git a/CHANGES b/CHANGES index 437ed9f248..aa80f5aa2f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +5.2.0-dev.407 | 2022-12-06 10:01:45 +0100 + + * Added several events for detailed info on the SSH2 key init directions (Joost Jansen) + 5.2.0-dev.404 | 2022-12-05 10:33:53 +0100 * Expose PA_ENC_TIMESTAMP to script land (nadavkluger) diff --git a/NEWS b/NEWS index 618a25cf49..180de7c98d 100644 --- a/NEWS +++ b/NEWS @@ -140,6 +140,10 @@ New Functionality - Add two BIFs ``get_identifier_declaring_script()`` and ``get_record_field_declaring_script()`` to query the declaring scripts for identifiers and record fields from Zeek scripts. +- Extend the SSH analyzer to produce new events (``ssh2_ecc_init``, + ``ssh2_gh_gex_init``, ``ssh2_gss_init``, ssh2_rsa_secret``) to detect + when SSH client and server roles are reversed. + Changed Functionality --------------------- diff --git a/VERSION b/VERSION index c208f02179..7c2bb10a8d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.2.0-dev.404 +5.2.0-dev.407 diff --git a/src/analyzer/protocol/ssh/events.bif b/src/analyzer/protocol/ssh/events.bif index 451f445e89..f075581689 100644 --- a/src/analyzer/protocol/ssh/events.bif +++ b/src/analyzer/protocol/ssh/events.bif @@ -7,11 +7,12 @@ ## ## version: The identification string ## -## .. zeek:see:: 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 +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh_server_version%(c: connection, version: string%); ## An :abbr:`SSH (Secure Shell)` Protocol Version Exchange message @@ -23,11 +24,12 @@ event ssh_server_version%(c: connection, version: string%); ## ## version: The identification string ## -## .. zeek:see:: ssh_server_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 +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh_client_version%(c: connection, version: string%); ## This event is generated when an :abbr:`SSH (Secure Shell)` @@ -45,10 +47,11 @@ event ssh_client_version%(c: connection, version: string%); ## unauthenticated access, which some servers support. ## ## .. zeek:see:: ssh_server_version ssh_client_version 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 +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh_auth_successful%(c: connection, auth_method_none: bool%); ## This event is generated when an :abbr:`SSH (Secure Shell)` @@ -74,11 +77,12 @@ event ssh_auth_successful%(c: connection, auth_method_none: bool%); ## authenticated: This is true if the analyzer detected a ## successful connection from the authentication attempt. ## -## .. zeek:see:: ssh_server_version ssh_client_version -## ssh_auth_successful ssh_auth_failed ssh_auth_result +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 +## ssh2_gss_error ssh2_ecc_key ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh_auth_attempted%(c: connection, authenticated: bool%); ## During the initial :abbr:`SSH (Secure Shell)` key exchange, each @@ -96,11 +100,12 @@ event ssh_auth_attempted%(c: connection, authenticated: bool%); ## capabilities: The list of algorithms and languages that the sender ## advertises support for, in order of preference. ## -## .. zeek:see:: ssh_server_version ssh_client_version -## ssh_auth_successful ssh_auth_failed ssh_auth_result -## ssh_auth_attempted ssh2_server_host_key ssh1_server_host_key +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 +## ssh2_gss_error ssh2_ecc_key ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh_capabilities%(c: connection, cookie: string, capabilities: SSH::Capabilities%); ## During the :abbr:`SSH (Secure Shell)` key exchange, the server @@ -113,11 +118,12 @@ event ssh_capabilities%(c: connection, cookie: string, capabilities: SSH::Capabi ## key: The server's public host key. Note that this is the public key ## itself, and not just the fingerprint or hash. ## -## .. zeek:see:: ssh_server_version ssh_client_version -## ssh_auth_successful ssh_auth_failed ssh_auth_result -## ssh_auth_attempted ssh_capabilities ssh1_server_host_key -## ssh_server_host_key ssh_encrypted_packet ssh2_dh_server_params -## ssh2_gss_error ssh2_ecc_key +## .. zeek:see:: ssh_server_version ssh_client_version 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 ssh2_ecc_init ssh2_dh_gex_init ssh2_gss_init +## ssh2_rsa_secret event ssh2_server_host_key%(c: connection, key: string%); ## During the :abbr:`SSH (Secure Shell)` key exchange, the server @@ -139,11 +145,12 @@ event ssh2_server_host_key%(c: connection, key: string%); ## ## 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 +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 +## ssh2_gss_error ssh2_ecc_key ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh1_server_host_key%(c: connection, modulus: string, exponent: string%); ## During the :abbr:`SSH (Secure Shell)` key exchange, the server @@ -167,11 +174,12 @@ event ssh1_server_host_key%(c: connection, modulus: string, exponent: string%); ## 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 +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 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)` @@ -189,11 +197,12 @@ event ssh_server_host_key%(c: connection, hash: string%); ## len: The length of the :abbr:`SSH (Secure Shell)` payload, in ## bytes. Note that this ignores reassembly, as this is unknown. ## -## .. 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 ssh2_dh_server_params -## ssh2_gss_error ssh2_ecc_key +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh_encrypted_packet%(c: connection, orig: bool, len: count%); ## Generated if the connection uses a Diffie-Hellman Group Exchange @@ -207,11 +216,12 @@ event ssh_encrypted_packet%(c: connection, orig: bool, len: count%); ## ## q: The DH generator. ## -## .. 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_gss_error ssh2_ecc_key +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret 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 @@ -227,11 +237,12 @@ event ssh2_dh_server_params%(c: connection, p: string, q: string%); ## ## err_msg: Detailed human-readable error message ## -## .. 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_ecc_key +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret event ssh2_gss_error%(c: connection, major_status: count, minor_status: count, err_msg: string%); ## The :abbr:`ECDH (Elliptic Curve Diffie-Hellman)` and @@ -241,15 +252,87 @@ event ssh2_gss_error%(c: connection, major_status: count, minor_status: count, e ## server's ephemeral public key is seen. For more information, see: ## :rfc:`5656#section-4`. ## -## c: The connection +## c: The connection. ## ## is_orig: Did this message come from the originator? ## ## q: The ephemeral public 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_server_host_key ssh_encrypted_packet -## ssh2_dh_server_params ssh2_gss_error +## .. zeek:see:: ssh_server_version ssh_client_version ssh_auth_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret 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_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret +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_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret +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_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret +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_failed +## ssh_auth_result ssh_auth_successful 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 ssh2_ecc_init ssh2_dh_gex_init +## ssh2_gss_init ssh2_rsa_secret +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 0000000000..8ddc4acc1a Binary files /dev/null and b/testing/btest/Traces/ssh/reverse-ssh.pcap differ diff --git a/testing/btest/scripts/base/protocols/ssh/ssh-reverse-connection.zeek b/testing/btest/scripts/base/protocols/ssh/ssh-reverse-connection.zeek new file mode 100644 index 0000000000..cdf9ae1b1f --- /dev/null +++ b/testing/btest/scripts/base/protocols/ssh/ssh-reverse-connection.zeek @@ -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"); + } +} 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"); +}