CVE-2021-40818: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') (CWE-120)
value: scheme/webauthn.c in Glewlwyd SSO server through 2.5.3 has a buffer overflow during FIDO2 signature validation in webauthn registration.
CWE description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
CVSS v3 base score: 9.8
Published: 2021-09-08T22:15Z
Repository: https://github.com/babelouest/glewlwyd
Language: C
Files changed: src/scheme/webauthn.c
Commit date: 2021-06-14 19:40:56 -0400
Commit message: Fix fido2 signature validation bug

Diff: diff --git a/src/scheme/webauthn.c b/src/scheme/webauthn.c
index 28240552..5b4eb8a4 100644
--- a/src/scheme/webauthn.c
+++ b/src/scheme/webauthn.c
@@ -1541,11 +1541,11 @@ static json_t * check_attestation_fido_u2f(json_t * j_params, unsigned char * cr
   int i, ret;
   char * message = NULL;
   gnutls_pubkey_t pubkey = NULL;
   gnutls_x509_crt_t cert = NULL;
   gnutls_datum_t cert_dat, data, signature, cert_issued_by;
-  unsigned char data_signed[200], client_data_hash[32], cert_export[32], cert_export_b64[64];
+  unsigned char * data_signed = NULL, client_data_hash[32], cert_export[32], cert_export_b64[64];
   size_t data_signed_offset = 0, client_data_hash_len = 32, cert_export_len = 32, cert_export_b64_len = 0;
   
   if (j_error != NULL) {
     do {
       if (gnutls_x509_crt_init(&cert)) {
@@ -1630,10 +1630,16 @@ static json_t * check_attestation_fido_u2f(json_t * j_params, unsigned char * cr
       if (sig == NULL || !cbor_isa_bytestring(sig)) {
         json_array_append_new(j_error, json_string("Error sig is not a bytestring"));
         break;
       }
       
+      if ((data_signed = o_malloc(rpid_hash_len+client_data_hash_len+credential_id_len+cert_x_len+cert_y_len+2)) == NULL) {
+        y_log_message(Y_LOG_LEVEL_DEBUG, "check_attestation_fido_u2f - Error allocating data_signed");
+        json_array_append_new(j_error, json_string("Internal error"));
+        break;
+      }
+      
       // Build bytestring to verify signature
       data_signed[0] = 0x0;
       data_signed_offset = 1;
       
       memcpy(data_signed+data_signed_offset, rpid_hash, rpid_hash_len);
@@ -1664,10 +1670,11 @@ static json_t * check_attestation_fido_u2f(json_t * j_params, unsigned char * cr
       if (gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA256, 0, &data, &signature)) {
         json_array_append_new(j_error, json_string("Invalid signature"));
       }
       
     } while (0);
+    o_free(data_signed);
     
     if (json_array_size(j_error)) {
       j_return = json_pack("{sisO}", "result", G_ERROR_PARAM, "error", j_error);
     } else {
       j_return = json_pack("{sis{ss%}}", "result", G_OK, "data", "certificate", cert_export_b64, cert_export_b64_len);

Vulnerable code:   unsigned char data_signed[200], client_data_hash[32], cert_export[32], cert_export_b64[64];
Fixed code:   unsigned char * data_signed = NULL, client_data_hash[32], cert_export[32], cert_export_b64[64];
      if ((data_signed = o_malloc(rpid_hash_len+client_data_hash_len+credential_id_len+cert_x_len+cert_y_len+2)) == NULL) {
        y_log_message(Y_LOG_LEVEL_DEBUG, "check_attestation_fido_u2f - Error allocating data_signed");
        json_array_append_new(j_error, json_string("Internal error"));
        break;
      }
      
    o_free(data_signed);