Vulnerability: 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.
Vulnerability ID: CVE-2020-11940
CWE: CWE-125
Severity score: 2.9
Project: https://github.com/ntop/nDPI
Published: 2020-04-23
File: src/lib/protocols/ssh.c
Commit message: ssh: adds systematic bounds checks in concat_hash_string

cf GHSL-2020-052
Commit author: Philippe Antoine

Vulnerable version (before fix):
 static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   buf[buf_out_len++] = ';';   offset += len;    /* ssh.server_host_key_algorithms [None] */   len = ntohl(*(u_int32_t*)&packet->payload[offset]);   offset += 4 + len;    /* ssh.encryption_algorithms_client_to_server [C] */   len = ntohl(*(u_int32_t*)&packet->payload[offset]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } else     offset += 4 + len;    /* ssh.encryption_algorithms_server_to_client [S] */   len = ntohl(*(u_int32_t*)&packet->payload[offset]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } else     offset += 4 + len;    /* ssh.mac_algorithms_client_to_server [C] */   len = ntohl(*(u_int32_t*)&packet->payload[offset]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } else     offset += 4 + len;    /* ssh.mac_algorithms_server_to_client [S] */   len = ntohl(*(u_int32_t*)&packet->payload[offset]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } else     offset += 4 + len;    /* ssh.compression_algorithms_server_to_client [S] */   len = ntohl(*(u_int32_t*)&packet->payload[offset]); 

Fixed version (after fix):
 static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   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]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } 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]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } 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]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } 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]);  static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,   } 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]); 

Patch:
patch: @@ -110,10 +110,14 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
   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]);
 
@@ -130,6 +134,8 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
   } 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]);
 
@@ -146,6 +152,8 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
   } 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]);
 
@@ -162,6 +170,8 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
   } 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]);
 
@@ -195,6 +205,8 @@ static u_int16_t concat_hash_string(struct ndpi_packet_struct *packet,
   } 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]);
path: src/lib/protocols/ssh.c