[gnutls-dev] more than one trusted certificate - buffer overflow

Max Kellermann max at duempel.org
Wed Feb 1 14:38:49 CET 2006


Hi,

I'm getting bus errors when I try to add more than one certificate
with gnutls_certificate_set_x509_trust().  Backtrace:

#0  _gnutls_x509_crt_get_raw_dn2 (cert=0x4449657571696e,
 whom=0x2aaaaac2a127 "issuer", start=0x7fffffe93940) at x509.c:1148
#1  0x00002aaaaabfe773 in generate_rdn_seq (res=0x53ac20) at
 gnutls_x509.c:1030
#2  0x00002aaaaabfed3d in gnutls_certificate_set_x509_trust
 (res=0x53ac20, ca_list=0x7fffffe93d60, ca_list_size=2)
    at gnutls_x509.c:1344
#3  0x000000000040371c in reload_credentials (instance=0x7fffffe93d20)
 at server/wrapper.c:458
[...]

I'm using libgnutls12 1.2.9-1 (Debian) on AMD64.  CVS HEAD still
carries this bug.

I found strange code in this function, see gnutls_x509.c lines 1312+:

  for (i = 0; i < ca_list_size; i++) {
      ret = gnutls_x509_crt_init(&res->x509_ca_list[i +
                                 res->x509_ncas]);
      [..]
      res->x509_ncas++;
  }

Both "i" and "res->x509_ncas" are incremented in every iteration, that
means, only even indices are being initialized - and it will overflow
the "res->x509_ca_list" buffer.

The same bug is present in gnutls_certificate_set_x509_crl().

Valgrind confirmed my theory:

Invalid write of size 8
   at 0x4B69C3F: gnutls_x509_crt_init (x509.c:54)
   by 0x4B5ACF4: gnutls_certificate_set_x509_trust (gnutls_x509.c:1328)
   by 0x40371B: reload_credentials (wrapper.c:458)
   by 0x40392C: init_tls (wrapper.c:523)
   by 0x404D25: main (wrapper.c:1118)

Solution: don't add "i" and "res->x509_ncas", just "res->x509_ncas"
gives us the correct index.  See patch.

You might need a lot of fantasy to imagine a remote exploit for this
buffer overflow, but the fact that this bug exists, shows that nobody
has ever tried to load more than one trusted certificate into
libgnutls...

Max

-------------- next part --------------
--- gnutls12-1.2.9/lib/gnutls_x509.c.orig	2006-02-01 14:24:37.778492250 +0100
+++ gnutls12-1.2.9/lib/gnutls_x509.c	2006-02-01 14:24:59.971879250 +0100
@@ -1325,17 +1325,17 @@
     }
 
     for (i = 0; i < ca_list_size; i++) {
-	ret = gnutls_x509_crt_init(&res->x509_ca_list[i + res->x509_ncas]);
+	ret = gnutls_x509_crt_init(&res->x509_ca_list[res->x509_ncas]);
 	if (ret < 0) {
 	    gnutls_assert();
 	    return ret;
 	}
 
-	ret = _gnutls_x509_crt_cpy(res->x509_ca_list[i + res->x509_ncas],
+	ret = _gnutls_x509_crt_cpy(res->x509_ca_list[res->x509_ncas],
 				   ca_list[i]);
 	if (ret < 0) {
 	    gnutls_assert();
-	    gnutls_x509_crt_deinit(res->x509_ca_list[i + res->x509_ncas]);
+	    gnutls_x509_crt_deinit(res->x509_ca_list[res->x509_ncas]);
 	    return ret;
 	}
 	res->x509_ncas++;
@@ -1615,7 +1615,7 @@
     }
 
     for (i = 0; i < crl_list_size; i++) {
-	ret = _gnutls_x509_crl_cpy(res->x509_crl_list[i + res->x509_ncrls],
+	ret = _gnutls_x509_crl_cpy(res->x509_crl_list[res->x509_ncrls],
 				   crl_list[i]);
 	if (ret < 0) {
 	    gnutls_assert();


More information about the Gnutls-dev mailing list