diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..0e869d7 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,43 @@ +BSD 3-Clause License + +Copyright (c) 2024, Corelight, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +___________________________________________________________________________ + +Copyright (c) 2018, Salesforce.com, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0aeed9 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# "HASSH" - a Profiling Method for SSH Clients and Servers. + +
+ + +
+ + +"HASSH" is a network fingerprinting standard which can be used to identify specific Client and Server SSH implementations. The fingerprints can be easily stored, searched and shared in the form of an MD5 fingerprint. + +[![License: BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) +## What can HASSH help with: +- Use in highly controlled, well understood environments, where any fingerprints outside of a known good set are alertable. +- It is possible to detect, control and investigate brute force or Cred Stuffing password attempts at a higher level of granularity than IP Source - which may be impacted by NAT or botnet-like behaviour. The hassh will be a feature of the specific Client software implementation being used, even if the IP is NATed such that it is shared by many other SSH clients. +- Detect covert exfiltration of data within the components of the Client algorithm sets. In this case, a specially coded SSH Client can send data outbound from a trusted to a less trusted environment within a series of SSH_MSG_KEXINIT packets. In a scenario similar to the more known exfiltration via DNS, data could be sent as a series of attempted, but incomplete and unlogged connections to an SSH server controlled by bad actors who can then record, decode and reconstitute these pieces of data into their original form. Until now such attempts - much less the contents of the clear text packets - are not logged even by mature packet analyzers or on end point systems. Detection of this style of exfiltration can now be performed easily by using anomaly detection or alerting on SSH Clients with multiple different hassh +- Use in conjunction with other contextual indicators, for example detect Network discovery and Lateral movement attempts by unusual hassh such as those used by Paramiko, Powershell, Ruby, Meterpreter, Empire. +- Share malicious hassh as Indicators of Compromise. +- Create an additional level of Client application control, for example one could block all Clients from connecting to an SSH server that are outside of an approved known set of hassh values. +- Contribute to Non Repudiation in a Forensic context - at a higher level of abstraction than IPSource - which may be impacted by NAT, or where multiple IP Sources are used. +- Detect Deceptive Applications. Eg a hasshServer value known to belong to the Cowry/Kippo SSH honeypot server installation, which is purporting to be a common OpenSSH server in the Server String. +- Detect devices having a hassh known to belong to IOT embedded systems. Examples may include cameras, mics, keyloggers, wiretaps that could be easily be hidden from view and communicating quietly over encrypted channels back to a control server. + +## How does HASSH work: +"hassh" and "hasshServer" are MD5 hashes constructed from a specific set of algorithms that are supported by various SSH Client and Server Applications. These algorithms are exchanged after the initial TCP three-way handshake as clear-text packets known as "SSH_MSG_KEXINIT" messages, and are an integral part of the setup of the final encrypted SSH channel. +The existence and ordering of these algorithms can be unique enough such that it can be used as a fingerprint to help identify the underlying Client and Server application or unique implementation, regardless of higher level ostensible identifiers such as "Client" or "Server" strings. ++ +
+ +## Example 1: Client Fingerprinting - the "hassh" +For the "Cyberduck" SFTP client ```SSH-2.0-Cyberduck/6.7.1.28683 (Mac OS X/10.13.6) (x86_64)``` , the set of supported algorithms is as follows : + +|Function|Algorithms seen in SSH_MSG_KEXINIT packets| +| ------------- | ------------- | +|Key Exchange methods| ```curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group14-sha256,diffie-hellman-group15-sha512,diffie-hellman-group16-sha512,diffie-hellman-group17-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256@ssh.com,diffie-hellman-group15-sha256,diffie-hellman-group15-sha256@ssh.com,diffie-hellman-group15-sha384@ssh.com,diffie-hellman-group16-sha256,diffie-hellman-group16-sha384@ssh.com,diffie-hellman-group16-sha512@ssh.com,diffie-hellman-group18-sha512@ssh.com```| +|Encryption| ```aes128-cbc,aes128-ctr,aes192-cbc,aes192-ctr,aes256-cbc,aes256-ctr,blowfish-cbc,blowfish-ctr,cast128-cbc,cast128-ctr,idea-cbc,idea-ctr,serpent128-cbc,serpent128-ctr,serpent192-cbc,serpent192-ctr,serpent256-cbc,serpent256-ctr,3des-cbc,3des-ctr,twofish128-cbc,twofish128-ctr,twofish192-cbc,twofish192-ctr,twofish256-cbc,twofish256-ctr,twofish-cbc,arcfour,arcfour128,arcfour256```| +|Message Authentication| ```hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96,hmac-sha2-256,hmac-sha2-512```| +|Compression| ```zlib@openssh.com,zlib,none```| + +Concatenating these algorithms together with a delimiter of ";" gives the hasshAlgorithms, which is useful for detailed analysis. +```curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group14-sha256,diffie-hellman-group15-sha512,diffie-hellman-group16-sha512,diffie-hellman-group17-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256@ssh.com,diffie-hellman-group15-sha256,diffie-hellman-group15-sha256@ssh.com,diffie-hellman-group15-sha384@ssh.com,diffie-hellman-group16-sha256,diffie-hellman-group16-sha384@ssh.com,diffie-hellman-group16-sha512@ssh.com,diffie-hellman-group18-sha512@ssh.com;aes128-cbc,aes128-ctr,aes192-cbc,aes192-ctr,aes256-cbc,aes256-ctr,blowfish-cbc,blowfish-ctr,cast128-cbc,cast128-ctr,idea-cbc,idea-ctr,serpent128-cbc,serpent128-ctr,serpent192-cbc,serpent192-ctr,serpent256-cbc,serpent256-ctr,3des-cbc,3des-ctr,twofish128-cbc,twofish128-ctr,twofish192-cbc,twofish192-ctr,twofish256-cbc,twofish256-ctr,twofish-cbc,arcfour,arcfour128,arcfour256;hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96,hmac-sha2-256,hmac-sha2-512;zlib@openssh.com,zlib,none``` + +Finally the hassh is simply the MD5 of hasshAlgorithms, and is used for storage, searching and sharing. Some examples follow: +``` +de30354b88bae4c2810426614e1b6976 Powershell Renci.SshNet.SshClient.0.0.1 (used by Empire exploit modules) +fafc45381bfde997b6305c4e1600f1bf Ruby/Net::SSH_5.0.2 x86_64-linux (used by Metasploit exploit modules) +b5752e36ba6c5979a575e43178908adf Python Paramiko_2.4.1 (used by Metasploit exploit modules) +16f898dd8ed8279e1055350b4e20666c Dropbear_2012.55 (used in IOT embedded systems) +8a8ae540028bf433cd68356c1b9e8d5b CyberDuck Version 6.7.1 (28683) +06046964c022c6407d15a27b12a6a4fb OpenSSH_7.7p1 Ubuntu-4 +``` + +## Example 2: Server Fingerprinting - the "hasshServer" +For a standard SSH-2.0-OpenSSH_5.3 SSH server, the set of supported algorithms is as follows : + +|Function|Algorithms seen in SSH_MSG_KEXINIT packets| +| ------------- | ------------- | +|Key Exchange methods| ```diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1```| +|Encryption| ```aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se```| +|Message Authentication| ```hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96```| +|Compression| ```none,zlib@openssh.com```| + +Concatenating these algorithms together with a delimiter of ";" gives the hasshServerAlgorithms, which is useful for detailed analysis. +```diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1;aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se;hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96;none,zlib@openssh.com``` + +Finally the hasshServer is simply the MD5 of hasshServerAlgorithms, some examples follow: +``` +c1c596caaeb93c566b8ecf3cae9b5a9e SSH-2.0-dropbear_2016.74 +d93f46d063c4382b6232a4d77db532b2 SSH-2.0-dropbear_2016.72 +2dd9a9b3dbebfaeec8b8aabd689e75d2 SSH-2.0-AWSCodeCommit +696e7f84ac571fdf8fa5073e64ee2dc8 SSH-2.0-FTP +``` + +## Options +By default, the raw algorithm string and the key algorithm are logged, and can be controlled by setting these boolean variables in the script. +``` +option log_raw_hasshAlgorithms = T; +option log_key_algorithm = T; +``` + +## References: +- [Salesforce Engineering blog](https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c) +- [BSides 2019 - HASSH - a Profiling Method for SSH Clients and Servers](https://github.com/benjeems/Presentations/blob/master/BSides%202019%20%20-%20HASSH%20-%20a%20Profiling%20Method%20for%20SSH%20Clients%20and%20Servers.pdf) +- [RFC4253 The Secure Shell (SSH) Transport Layer Protocol](https://www.ietf.org/rfc/rfc4253.txt) + +## Credits: +hassh and hasshServer were conceived and developed by [Ben Reardon](mailto:benjeems@gmail.com) within the Detection Cloud Team at Salesforce, with inspiration and contributions from Adel Karimi (@0x4d31) and the JA3 crew. \ No newline at end of file diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..f9aa438 Binary files /dev/null and b/images/logo.png differ diff --git a/images/packet_sequence.png b/images/packet_sequence.png new file mode 100644 index 0000000..57fc33a Binary files /dev/null and b/images/packet_sequence.png differ diff --git a/scripts/__load__.zeek b/scripts/__load__.zeek new file mode 100644 index 0000000..c8698a1 --- /dev/null +++ b/scripts/__load__.zeek @@ -0,0 +1 @@ +@load ./hassh.zeek diff --git a/scripts/hassh.zeek b/scripts/hassh.zeek new file mode 100644 index 0000000..866a0b0 --- /dev/null +++ b/scripts/hassh.zeek @@ -0,0 +1,89 @@ +module SSH; + +redef record SSH::Info += { + # The version is just in case the method changes in the future, + # as it may be handy to reference the version historically. + hasshVersion: string &log &default="1.0"; + + # Client/server hashes. + hassh: string &log &optional; + hasshServer: string &log &optional; + + # Server host key as seen by a client. + cshka: string &log &optional; + + # The algorithms that went into the client hash. + hasshAlgorithms: string &log &optional; + + # Server host key as seen by a server. + sshka: string &log &optional; + + # The algorithms that went into the server hash. + hasshServer_Algorithms: string &log &optional; +}; + +option log_raw_hassh_algorithms = T; +option log_key_algorithm = T; + +# Takes key exchange, encryption, mac, and compression algorithm vectors and +# returns the corresponding algorithm list. +function extract_algo_list(kex: string_vec, enc: string_vec, mac: string_vec, + cmp: string_vec) : string + { + local kex_list = join_string_vec(kex, ","); + local enc_list = join_string_vec(enc, ","); + local mac_list = join_string_vec(mac, ","); + local cmp_list = join_string_vec(cmp, ","); + + return kex_list + ";" + enc_list + ";" + mac_list + ";" + cmp_list; + } + +# Build client fingerprint. +function get_hassh(c: connection, capabilities: SSH::Capabilities) + { + local algo_list = extract_algo_list( + capabilities$kex_algorithms, + capabilities$encryption_algorithms$client_to_server, + capabilities$mac_algorithms$client_to_server, + capabilities$compression_algorithms$client_to_server); + + c$ssh$hassh = md5_hash(algo_list); + + if ( log_raw_hassh_algorithms ) + c$ssh$hasshAlgorithms = algo_list; + + if ( log_key_algorithm ) + c$ssh$cshka = join_string_vec(capabilities$server_host_key_algorithms, ","); + } + +# Build server fingerprint. +function get_hasshServer(c: connection, capabilities: SSH::Capabilities) + { + local algo_list = extract_algo_list( + capabilities$kex_algorithms, + capabilities$encryption_algorithms$server_to_client, + capabilities$mac_algorithms$server_to_client, + capabilities$compression_algorithms$server_to_client); + + c$ssh$hasshServer = md5_hash(algo_list); + + if ( log_raw_hassh_algorithms ) + c$ssh$hasshServer_Algorithms = algo_list; + + if ( log_key_algorithm ) + c$ssh$sshka = join_string_vec(capabilities$server_host_key_algorithms, ","); + } + +event ssh_capabilities(c: connection, cookie: string, + capabilities: SSH::Capabilities) + { + # This should really never apply, but just in case. + if ( ! c?$ssh ) + return; + + if ( capabilities$is_server && ! c$ssh?$hasshServer ) + get_hasshServer(c, capabilities); + + else if ( ! capabilities$is_server && ! c$ssh?$hassh ) + get_hassh(c, capabilities); + } diff --git a/testing/.gitignore b/testing/.gitignore new file mode 100644 index 0000000..1feec7c --- /dev/null +++ b/testing/.gitignore @@ -0,0 +1,3 @@ +.btest.failed.dat +.tmp +.DS_STORE \ No newline at end of file diff --git a/testing/Baseline/tests.ssh_zeek_test_pcaps/ssh_cut.log b/testing/Baseline/tests.ssh_zeek_test_pcaps/ssh_cut.log new file mode 100644 index 0000000..2d7917e --- /dev/null +++ b/testing/Baseline/tests.ssh_zeek_test_pcaps/ssh_cut.log @@ -0,0 +1,43 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +192.150.186.169 49244 131.159.14.23 22 SSH-2.0-OpenSSH_3.8.1p1 SSH-1.99-OpenSSH_3.9p1 c4fd9343cba76d12f0dd523fbe7c4da1 f430cd6761697a6a658ee1d45ed22e49 +10.0.0.1 59139 10.0.0.2 22 SSH-1.99-Cisco-1.25 SSH-2.0-Cisco-1.25 3cc67862bceac0f334c62ad1b76895b4 3cc67862bceac0f334c62ad1b76895b4 +172.16.238.1 49656 172.16.238.131 80 SSH-2.0-OpenSSH_5.2 SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3 21b457a327ce7a2d4fce5ef2c42400bd 60205d0b53ffd441ead5c43b5a6f1bc7 +192.168.1.79 51880 131.159.21.1 22 SSH-2.0-OpenSSH_5.9 SSH-2.0-OpenSSH_5.8 fded76fff260754db84bd4725a931b7e 60205d0b53ffd441ead5c43b5a6f1bc7 +10.0.0.18 40184 128.2.6.88 41644 SSH-2.0-OpenSSH_6.6 SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1.1 e30029a55fea2fcd3501023fb659bfae ce3c327f37ea2ec21f317fbc3fd1ea43 +192.168.2.1 57189 192.168.2.158 22 SSH-2.0-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 1f120ecfc2c57fbdeaf66b93a3bf26ee ba6d3d2aecbd0d91b01dfa7828110d70 +192.168.2.1 57191 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 55179 192.168.2.158 2200 SSH-2.0-OpenSSH_6.2 SSH-2.0-paramiko_1.15.2 1f120ecfc2c57fbdeaf66b93a3bf26ee d72f74b08466652d162ca02ad197b9ad +192.168.2.1 56594 192.168.2.158 22 SSH-1.5-OpenSSH_5.3 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 56821 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 56837 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 56845 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 56875 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 56878 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 56940 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 57831 192.168.2.158 22 SSH-1.5-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 - - +192.168.2.1 59246 192.168.2.158 22 SSH-2.0-OpenSSH_6.2 SSH-1.99-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 3b310af105a6d0567dc00a90451b0e6e ba6d3d2aecbd0d91b01dfa7828110d70 +192.168.1.32 41164 128.2.10.238 22 SSH-2.0-OpenSSH_6.6p1-hpn14v4 SSH-1.99-OpenSSH_3.4+p1+gssapi+OpenSSH_3.7.1buf_fix+2006100301 e30029a55fea2fcd3501023fb659bfae 5280acc8be4a17ac96c05b6f3bdaec60 +192.168.1.32 33910 128.2.13.133 22 SSH-2.0-OpenSSH_6.6p1-hpn14v4 SSH-2.0-OpenSSH_5.3 e30029a55fea2fcd3501023fb659bfae 0f5053d1cc689128b6db47f340f3285f +192.168.1.32 41268 128.2.10.238 22 SSH-2.0-OpenSSH_6.6 SSH-1.99-OpenSSH_3.4+p1+gssapi+OpenSSH_3.7.1buf_fix+2006100301 e30029a55fea2fcd3501023fb659bfae 5280acc8be4a17ac96c05b6f3bdaec60 +192.168.1.31 52294 192.168.1.32 22 SSH-2.0-OpenSSH_6.7 SSH-2.0-OpenSSH_6.7 777e66d81dadd6002bf417dc5e1c61df 41ed548e9e885f199ea6919370d83c68 +192.168.1.31 51489 192.168.1.32 22 SSH-2.0-OpenSSH_6.7 SSH-2.0-OpenSSH_6.7 a708ee258c30a58517040d6611dce408 41ed548e9e885f199ea6919370d83c68 +192.168.1.32 58641 131.103.20.168 22 SSH-2.0-OpenSSH_6.7 SSH-2.0-OpenSSH_5.3 46c5bd9748882f1a5d75753fb7d47a61 b1c6c0d56317555b85c7005a3de29325 +192.168.1.32 58646 131.103.20.168 22 SSH-2.0-OpenSSH_6.7 SSH-2.0-OpenSSH_5.3 46c5bd9748882f1a5d75753fb7d47a61 b1c6c0d56317555b85c7005a3de29325 +192.168.1.32 58649 131.103.20.168 22 SSH-2.0-OpenSSH_6.7 SSH-2.0-OpenSSH_5.3 46c5bd9748882f1a5d75753fb7d47a61 b1c6c0d56317555b85c7005a3de29325 +192.168.56.1 55470 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55471 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55472 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55473 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55474 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55475 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55476 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55477 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55478 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55479 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.56.1 55480 192.168.56.103 22 SSH-2.0-OpenSSH_6.2 SSH-2.0-OpenSSH_6.7p1 Debian-3 1f120ecfc2c57fbdeaf66b93a3bf26ee 3711ee816d3ea9975d96c39c31c54299 +192.168.1.100 60906 192.168.1.32 22 SSH-2.0-OpenSSH_7.4 SSH-2.0-OpenSSH_7.5 0df0d56bb50c6b2426d8d40234bf1826 a95c22bf8e9b19ed0a5dc74bb2f9c613 +127.0.0.1 38202 127.0.0.1 22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 06046964c022c6407d15a27b12a6a4fb b12d2871a1189eff20364cf5333619ee +10.0.2.15 61251 192.168.57.3 22 SSH-2.0-PuTTY_Release_0.72 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 e77c2db7432e8cfbc42a96909a84fc8e b12d2871a1189eff20364cf5333619ee +127.0.0.1 57388 127.0.0.1 22 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1 ae8bd7dd09970555aa4c6ed22adbbf56 3ccd1778a76049721c71ad7d2bf62bbc +127.0.0.1 37524 127.0.0.1 2222 SSH-1.5-OpenSSH_6.6 SSH-1.5-OpenSSH_6.6 - - +10.0.0.1 48020 13.13.13.37 22 SSH-2.0-dropbear_2018.76 SSH-2.0-AsyncSSH_2.8.1 413e646031ea5204c5ec2fe2d5b7946e 18f369389d126cfeecade20e1ea5ff9b diff --git a/testing/Files/random.seed b/testing/Files/random.seed new file mode 100644 index 0000000..6956a2c --- /dev/null +++ b/testing/Files/random.seed @@ -0,0 +1,21 @@ +2983378351 +1299727368 +0 +310447 +0 +1409073626 +3975311262 +34130240 +1450515018 +1466150520 +1342286698 +1193956778 +2188527278 +3361989254 +3912865238 +3596260151 +517973768 +1462428821 +0 +2278350848 +32767 diff --git a/testing/Makefile b/testing/Makefile new file mode 100644 index 0000000..92538a1 --- /dev/null +++ b/testing/Makefile @@ -0,0 +1,8 @@ +test: + @btest -c btest.cfg -j -f diag.log + +zam: + @btest -c btest.cfg -j -a zam -f diag.log + +clean: + rm -rf .tmp diag.log diff --git a/testing/Scripts/README b/testing/Scripts/README new file mode 100644 index 0000000..8098fa4 --- /dev/null +++ b/testing/Scripts/README @@ -0,0 +1,7 @@ +Place helper scripts, such a btest-diff canonifiers, in this directory. +Note that Zeek versions 4.1 and newer include their btest tooling as part +of the installation. Take a look at the folder reported via + + zeek-config --btest_tools_dir + +for scripts, PRNG seeds, and pcaps you might be able to reuse. diff --git a/testing/Scripts/diff-remove-timestamps b/testing/Scripts/diff-remove-timestamps new file mode 100755 index 0000000..8ab13f5 --- /dev/null +++ b/testing/Scripts/diff-remove-timestamps @@ -0,0 +1,13 @@ +#! /usr/bin/env bash +# +# Replace anything which looks like timestamps with XXXs (including the #start/end markers in logs). + +# Get us "modern" regexps with sed. +if [ "$(uname)" == "Linux" ]; then + sed="sed -r" +else + sed="sed -E" +fi + +$sed 's/(0\.000000)|([0-9]{9,10}\.[0-9]{2,8})/XXXXXXXXXX.XXXXXX/g' | + $sed 's/^ *#(open|close).(19|20)..-..-..-..-..-..$/#\1 XXXX-XX-XX-XX-XX-XX/g' diff --git a/testing/Scripts/get-zeek-env b/testing/Scripts/get-zeek-env new file mode 100755 index 0000000..86975be --- /dev/null +++ b/testing/Scripts/get-zeek-env @@ -0,0 +1,40 @@ +#! /bin/sh +# +# BTest helper for getting values for Zeek-related environment variables. + +# shellcheck disable=SC2002 +base="$(dirname "$0")" +zeek_dist=$(cat "${base}/../../build/CMakeCache.txt" 2>/dev/null | grep ZEEK_DIST | cut -d = -f 2) + +if [ -n "${zeek_dist}" ]; then + if [ "$1" = "zeekpath" ]; then + "${zeek_dist}/build/zeek-path-dev" + elif [ "$1" = "zeek_plugin_path" ]; then + (cd "${base}/../.." && pwd) + elif [ "$1" = "path" ]; then + echo "${zeek_dist}/build/src:${zeek_dist}/aux/btest:${base}/:${zeek_dist}/aux/zeek-cut:$PATH" + else + echo "usage: $(basename "$0") " >&2 + exit 1 + fi +else + # Use Zeek installation for testing. In this case zeek-config must be in PATH. + if ! which zeek-config >/dev/null 2>&1; then + echo "zeek-config not found" >&2 + exit 1 + fi + + if [ "$1" = "zeekpath" ]; then + zeek-config --zeekpath + elif [ "$1" = "zeek_plugin_path" ]; then + # Combine the local tree and the system-wide path. This allows + # us to test on a local build or an installation made via zkg, + # which squirrels away the build. --cpk + echo "$(cd "${base}/../.." && pwd):$(zeek-config --plugin_dir)" + elif [ "$1" = "path" ]; then + echo "${PATH}" + else + echo "usage: $(basename "$0") " >&2 + exit 1 + fi +fi diff --git a/testing/Traces/ssh_zeek_test_pcaps.pcap b/testing/Traces/ssh_zeek_test_pcaps.pcap new file mode 100644 index 0000000..5cc9a72 Binary files /dev/null and b/testing/Traces/ssh_zeek_test_pcaps.pcap differ diff --git a/testing/btest.cfg b/testing/btest.cfg new file mode 100644 index 0000000..bfc4998 --- /dev/null +++ b/testing/btest.cfg @@ -0,0 +1,22 @@ +[btest] +TestDirs = tests +TmpDir = %(testbase)s/.tmp +BaselineDir = %(testbase)s/Baseline +IgnoreDirs = .tmp +IgnoreFiles = *.tmp *.swp #* *.trace .DS_Store + +[environment] +ZEEKPATH=`%(testbase)s/Scripts/get-zeek-env zeekpath`:/opt/bro/share/zeek/site/packages/corelight +ZEEK_PLUGIN_PATH=`%(testbase)s/Scripts/get-zeek-env zeek_plugin_path` +ZEEK_SEED_FILE=%(testbase)s/Files/random.seed +ZEEK=zeek +PATH=`%(testbase)s/Scripts/get-zeek-env path` +PACKAGE=%(testbase)s/../scripts +TZ=UTC +LC_ALL=C +TRACES=%(testbase)s/Traces +TMPDIR=%(testbase)s/.tmp +TEST_DIFF_CANONIFIER=%(testbase)s/Scripts/diff-remove-timestamps + +[environment-zam] +ZEEK_ZAM=1 diff --git a/testing/tests/ssh_zeek_test_pcaps.zeek b/testing/tests/ssh_zeek_test_pcaps.zeek new file mode 100644 index 0000000..38365fe --- /dev/null +++ b/testing/tests/ssh_zeek_test_pcaps.zeek @@ -0,0 +1,5 @@ +# @TEST-DOC: Test for creation of ssh.log and no reporter.log +# @TEST-EXEC: $ZEEK -Cr $TRACES/ssh_zeek_test_pcaps.pcap $PACKAGE %INPUT +# @TEST-EXEC: cat ssh.log | zeek-cut id.orig_h id.orig_p id.resp_h id.resp_p client server hassh hasshServer > ssh_cut.log +# @TEST-EXEC: btest-diff ssh_cut.log +# @TEST-EXEC: test ! -f reporter.log diff --git a/zkg.meta b/zkg.meta new file mode 100644 index 0000000..ad00bb9 --- /dev/null +++ b/zkg.meta @@ -0,0 +1,18 @@ +[package] +script_dir = scripts +test_command = cd testing && btest -c btest.cfg +summary = SSH client and server fingerprints. +description = HASSH is used to identify specific Client and Server SSH implementations. The fingerprints can be stored, searched and shared in the form of an MD5 fingerprint. This package logs components to ssh.log +tags = bro plugin, ssh, fingerprint, logging +version = 2.0 +depends = + zeek >=4.0.0 + +[template] +source = https://github.com/zeek/package-template +version = v3.1.0 +zkg_version = 2.14.0 + +[template_vars] +name = hassh +