diff options
author | Luca Deri <lucaderi@users.noreply.github.com> | 2020-07-25 16:17:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-25 16:17:24 +0200 |
commit | b26539d65a22aea3c91af631b56ef90452aa14c2 (patch) | |
tree | 093cf4b60c27d7956d45c6d2f4d3ac4958cdb75f | |
parent | 21e2e576146be8f4451d703c3e54a8208c4e4701 (diff) | |
parent | 6719fa30f9cfda5fe9d60b84e7afb442a9ea3517 (diff) |
Merge pull request #967 from MrRadix/dev
Ssh signature checking
-rw-r--r-- | python/ndpi.py | 2 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 4 | ||||
-rw-r--r-- | src/lib/protocols/ssh.c | 134 |
3 files changed, 116 insertions, 24 deletions
diff --git a/python/ndpi.py b/python/ndpi.py index 31abe53dc..547570b9d 100644 --- a/python/ndpi.py +++ b/python/ndpi.py @@ -306,6 +306,8 @@ typedef enum { NDPI_TLS_NOT_CARRYING_HTTPS, NDPI_SUSPICIOUS_DGA_DOMAIN, NDPI_MALFORMED_PACKET, + NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER, + NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER, /* Leave this as last member */ NDPI_MAX_RISK } ndpi_risk_enum; diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index ac2c7173c..1d33500ff 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -1525,10 +1525,10 @@ const char* ndpi_risk2str(ndpi_risk_enum risk) { return("Malformed packet"); case NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER: - return("SSH obsolete client version/cipher"); + return("SSH Obsolete client version/cipher"); case NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER: - return("SSH obsolete server version/cipher"); + return("SSH Obsolete server version/cipher"); default: snprintf(buf, sizeof(buf), "%d", (int)risk); diff --git a/src/lib/protocols/ssh.c b/src/lib/protocols/ssh.c index 5aca9b350..f1f0e1503 100644 --- a/src/lib/protocols/ssh.c +++ b/src/lib/protocols/ssh.c @@ -25,10 +25,15 @@ #include "ndpi_protocol_ids.h" #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_SSH +#define MAJOR_CUTOFF 7 +#define MINOR_CUTOFF 0 +#define PATCH_CUTOFF 0 #include "ndpi_api.h" #include "ndpi_md5.h" +#include <string.h> + /* HASSH - https://github.com/salesforce/hassh @@ -57,43 +62,128 @@ /* #define SSH_DEBUG 1 */ static void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); - + /* ************************************************************************ */ -static void ssh_analyse_signature_version(struct ndpi_detection_module_struct *ndpi_struct, +static void ssh_analyze_signature_version(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, char *str_to_check, u_int8_t is_client_signature) { + if (str_to_check == NULL) return; - /* - if(obsolete_ssh_version) - NDPI_SET_BIT(flow->risk, is_client_signature ? NDPI_SSH_OBSOLETE_CLIENT_SIGNATURE : NDPI_SSH_OBSOLETE_SERVER_SIGNATURE); - */ + int i; + int matches; + int major = 0; + int minor = 0; + int patch = 0; + u_int8_t version_match = 0; + u_int8_t obsolete_ssh_version = 0; + + const char *ssh_servers_strings[] = { + "SSH-%*f-OpenSSH_%d.%d.%d", /* OpenSSH */ + "SSH-%*f-APACHE-SSHD-%d.%d.%d", /* Apache MINA SSHD */ + "SSH-%*f-FileZilla_%d.%d.%d", /* FileZilla SSH*/ + "SSH-%*f-paramiko_%d.%d.%d", /* Paramiko SSH */ + "SSH-%*f-dropbear_%d.%d", /* Dropbear SSH */ + NULL, + }; + + int versions_cutoff[][3] = { + /* maj,min,patch */ + + {7,0,0}, /* OpenSSH */ + {2,5,1}, /* Apache MINA SSHD */ + {3,40,0}, /* FileZilla SSH */ + {2,4,0}, /* Paramiko SSH */ + {2020,0,0} /* Dropbear SSH (leave patch field as 0)*/ + + }; + + for (i = 0; ssh_servers_strings[i]; i++) { + matches = sscanf(str_to_check, ssh_servers_strings[i], &major, &minor, &patch); + + if (matches == 3 || matches == 2) { + version_match = 1; + break; + } + } + + if (!version_match) return; + + /* checking if is an old version */ + if (major < versions_cutoff[i][0]) obsolete_ssh_version = 1; + + else if (major == versions_cutoff[i][0]) { + if (minor < versions_cutoff[i][1]) obsolete_ssh_version = 1; + + else if (minor == versions_cutoff[i][1]) + if (patch < versions_cutoff[i][2]) obsolete_ssh_version = 1; + } + + if (obsolete_ssh_version) { + #ifdef SSH_DEBUG + printf("[SSH] [SSH Version: %d.%d.%d]\n", major, minor, patch); + #endif + + NDPI_SET_BIT(flow->risk, (is_client_signature ? NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER : NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER)); + } } /* ************************************************************************ */ static void ssh_analyse_cipher(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - char *cipher, u_int cipher_len, + char *ciphers, u_int cipher_len, u_int8_t is_client_signature) { - /* - List of obsolete ciphers can be found at - https://www.linuxminion.com/deprecated-ssh-cryptographic-settings/ - */ -#ifdef SSH_DEBUG - u_int i; - - printf("[%s] ", is_client_signature ? "CLIENT" : "SERVER"); - for(i=0; i<cipher_len; i++) - printf("%c", cipher[i]); + char *rem; + char *cipher; + u_int8_t found_obsolete_cipher = 0; + + const char *obsolete_ciphers[] = { + "arcfour256", + "arcfour128", + "3des-cbc", + "blowfish-cbc", + "cast128-cbc", + "arcfour", + NULL, + }; + + char *copy = (char*)ndpi_calloc(cipher_len, sizeof(char)); + if (copy == NULL) { + return; + } - printf("\n"); -#endif + if (strncpy(copy, ciphers, cipher_len) == NULL) + return; + + cipher = strtok_r(copy, ",", &rem); + + while (cipher && !found_obsolete_cipher) { + + for (int i = 0; obsolete_ciphers[i]; i++) { + if (strcmp(cipher, obsolete_ciphers[i]) == 0) { + found_obsolete_cipher = 1; + break; + } + } + + cipher = strtok_r(NULL, ",", &rem); + } + + if (found_obsolete_cipher) { + #ifdef SSH_DEBUG + printf("[SSH] [SSH obsolete cipher]\n"); + #endif + + NDPI_SET_BIT(flow->risk, (is_client_signature ? NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER : NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER)); + } + + ndpi_free(copy); } - + /* ************************************************************************ */ static int search_ssh_again(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { @@ -328,7 +418,7 @@ static void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct flow->protos.ssh.client_signature[len] = '\0'; ndpi_ssh_zap_cr(flow->protos.ssh.client_signature, len); - ssh_analyse_signature_version(ndpi_struct, flow, flow->protos.ssh.client_signature, 1); + ssh_analyze_signature_version(ndpi_struct, flow, flow->protos.ssh.client_signature, 1); #ifdef SSH_DEBUG printf("[SSH] [client_signature: %s]\n", flow->protos.ssh.client_signature); @@ -348,7 +438,7 @@ static void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct flow->protos.ssh.server_signature[len] = '\0'; ndpi_ssh_zap_cr(flow->protos.ssh.server_signature, len); - ssh_analyse_signature_version(ndpi_struct, flow, flow->protos.ssh.server_signature, 0); + ssh_analyze_signature_version(ndpi_struct, flow, flow->protos.ssh.server_signature, 0); #ifdef SSH_DEBUG printf("[SSH] [server_signature: %s]\n", flow->protos.ssh.server_signature); |