OpenSSL people,

First of all, many thanks for your excellent libraries. I apologize if
this issue has already been addressed or if I am writing to the wrong
mailing list.

The application I am developing makes very frequent calls to
d2i_X509_bio(), on untrusted data streams can sometimes be corrupt or
partly corrupt. I am seeing sudden blow-ups of the process: it
suddenly grows to a very large and apparently random size (e.g.,
200MB, 500MB, 800MB...) and keeps on running. This happens with both
engine-0.9.6b and engine-0.9.6c. I suspect the problem is in
d2i_X509()'s ASN1 parser.

I managed to partly reproduce the problem by running the program
tucked at the end of this message for about 20 to 30 minutes. I am
saying "partly", because with this program I did not manage to have
the process grow and keep on running; rather, it grows and immediately
segfaults with a huge core file. Both the original application (which
I am not able to debug directly) and the test program output a lot of
ASN1 errors from d2i_X509() and downwards.

Looking in crypto/asn1/asn1_lib.c:ASN1_get_object() I saw this:

    #if 0
            fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d  (%d > %d)\n", 
                    (int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
                    (int)(omax+ *pp));
    
    #endif
    #if 0
            if ((p+ *plength) > (omax+ *pp))
                    {
                    ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG);
                    /* Set this so that even if things are not long enough
                     * the values are set correctly */
                    ret|=0x80;
                    }
    #endif

Which seemed suspicious to me. Since *plength is read from the parsed
stream, corruption could make it be any number, which is, if not
sanity-checked, eventually fed to OPENSSL_malloc() and memcpy() by
ASN1_get_object()'s users. That could explain the blow-ups and the
crashes. Removing the #if and changing the test to

    if (*plength < 0 || *plength > (omax - (p - *pp)))

(p + *plength can wrap) got rid of the blow-ups and core files.

So:

- Was the test #if'd out on purpose? Is there a problem with putting
  it back? Do you have any recommendations?

- Could this explain also a blow-up without a segfault? Could
  something else?

- Is this a security issue? I imagine that a crafted invalid
  certificate could bring down a server, maybe even cause it to send
  sensitive information (because of the memcpy()).


Thanks in advance,

--
Adi Stav - developer
Topaz Prism R&D
Mercury Interactive
+972-3-5399481
[EMAIL PROTECTED]


--------------------------------------------------------------------

#include <stdlib.h>
#include <stdio.h>
#include <openssl/x509.h>

int main(int argc, char *argv[])
{
   unsigned char cert[10240], buf[10240], *p = cert;
   unsigned len;
   FILE *certfile;
   int stat;
   int i;

   OpenSSL_add_all_algorithms();
   ERR_load_crypto_strings();

   if (argc != 3) {
      fprintf(stderr, "usage: %s cert iterations\n", argv[0]);
      return 6;
   }  

   if (!(certfile = fopen(argv[1], "r"))) {
      perror(argv[1]);
      return 3;
   }

   i = atoi(argv[2]);
   
   while ((stat = fread(p, 1, sizeof cert - (p - cert), certfile)) > 0) {
      p += stat;
   }
   if (stat < 0) {
      perror(argv[1]);
      return 1;
   }
   len = p - cert;

   while (i--) {
      int randlen;
      X509 *x509;
      
      randlen = random() % 1500;
      
      memcpy(buf, cert, randlen);
      RAND_pseudo_bytes(buf + randlen, len - randlen);

      p = buf;
      if ((x509 = d2i_X509(NULL, &p, len))) {
         X509_free(x509);
      } else {
         ERR_print_errors_fp(stderr);
      }
   }

   return 0;
}
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to