CVE-2020-11940: Out-of-bounds Read (CWE-125)
value: In nDPI through 3.2 Stable, an out-of-bounds read in concat_hash_string in ssh.c can be exploited by a network-positioned attacker that can send malformed SSH protocol messages on a network segment monitored by nDPI's library.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.5
Published: 2020-04-23T15:15Z
Repository: https://github.com/ntop/nDPI
Language: C
Files changed: src/lib/protocols/ssh.c
Commit date: 2020-04-02 16:35:10 +0200
Commit message: ssh: adds systematic bounds checks in concat_hash_string

cf GHSL-2020-052

Diff: diff --git a/src/lib/protocols/ssh.c b/src/lib/protocols/ssh.c
index 853fbb24..292433e5 100644
--- a/src/lib/protocols/ssh.c
+++ b/src/lib/protocols/ssh.c
@@ -108,14 +108,18 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
   /* ssh.kex_algorithms [C/S] */
   strncpy(buf, (const char *)&packet->payload[offset], buf_out_len = len);
   buf[buf_out_len++] = ';';
   offset += len;
 
+  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
+    goto invalid_payload;
   /* ssh.server_host_key_algorithms [None] */
   len = ntohl(*(u_int32_t*)&packet->payload[offset]);
   offset += 4 + len;
 
+  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
+    goto invalid_payload;
   /* ssh.encryption_algorithms_client_to_server [C] */
   len = ntohl(*(u_int32_t*)&packet->payload[offset]);
 
   if(client_hash) {
     offset += 4;
@@ -128,10 +132,12 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
     buf[buf_out_len++] = ';';
     offset += len;
   } else
     offset += 4 + len;
 
+  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
+    goto invalid_payload;
   /* ssh.encryption_algorithms_server_to_client [S] */
   len = ntohl(*(u_int32_t*)&packet->payload[offset]);
 
   if(!client_hash) {
     offset += 4;
@@ -144,10 +150,12 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
     buf[buf_out_len++] = ';';
     offset += len;
   } else
     offset += 4 + len;
 
+  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
+    goto invalid_payload;
   /* ssh.mac_algorithms_client_to_server [C] */
   len = ntohl(*(u_int32_t*)&packet->payload[offset]);
 
   if(client_hash) {
     offset += 4;
@@ -160,10 +168,12 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
     buf[buf_out_len++] = ';';
     offset += len;
   } else
     offset += 4 + len;
 
+  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
+    goto invalid_payload;
   /* ssh.mac_algorithms_server_to_client [S] */
   len = ntohl(*(u_int32_t*)&packet->payload[offset]);
 
   if(!client_hash) {
     offset += 4;
@@ -193,10 +203,12 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
     buf_out_len += len;
     offset += len;
   } else
     offset += 4 + len;
 
+  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
+    goto invalid_payload;
   /* ssh.compression_algorithms_server_to_client [S] */
   len = ntohl(*(u_int32_t*)&packet->payload[offset]);
 
   if(!client_hash) {
     offset += 4;

Fixed code:   if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
    goto invalid_payload;
  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
    goto invalid_payload;
  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
    goto invalid_payload;
  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
    goto invalid_payload;
  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
    goto invalid_payload;
  if(offset+sizeof(u_int32_t) >= packet->payload_packet_len)
    goto invalid_payload;