Certified Secure

Certified Secure Advisory 14-01-2015-0.1 - PolarSSL

CVE 2015-1182

During a routine research session, Certified Secure found a "Use of uninitialized memory" vulnerability in the PolarSSL (https://polarssl.org) library. The vulnerability is present in the asn1_get_sequence_of routine that is used to parse ASN.1 sequences from X.509 certificates.

The vulnerability can be exploited using a specially crafted X.509 certificate.

Feedback received from PolarSSL on 14-01-2015: Upon receiving our advisory PolarSSL indicated they have independently found the same vulnerability during an internal audit process. A patch for this vulnerability will be released on 19-01-2015, see the official PolarSSL advisory.

Impact

When a user controlled X.509 certificate is parsed by the PolarSSL library, the vulnerability allows for Remote Code Execution and a Denial of Service. The most common vulnerable scenario is a server using the PolarSSL library to verify client certificates.

In this scenario a malicious client can exploit the server by presenting a crafted X.509 certificate. The vulnerability is triggered during parsing and before the actual validation of the certificate. Other scenarios include a malicious server presenting a crafted server certificate (exploiting the connecting clients) and any other (direct) callers of the X.509 parsing routines of the PolarSSL library

Vulnerable Versions

Confirmed in PolarSSL >= PolarSSL 1.0

Upgrading

Apply the official patch from the PolarSSL advisory

Upgrade for OpenVPN-NL will be made available at https://openvpn.fox-it.com

Unofficial patch for PolarSSL 1.3.9 available here

Projects using PolarSSL

This vulnerability may impact projects using the PolarSSL library.

https://polarssl.org/kb/generic/projects-using-polarssl

Nitty Gritty

library/asn1parse.c:asn1_get_sequence_of:

int asn1_get_sequence_of( unsigned char **p,
                          const unsigned char *end,
                          asn1_sequence *cur,
                          int tag)
{
    int ret;
    size_t len;
    asn1_buf *buf;

    /* Get main sequence tag */
    if( ( ret = asn1_get_tag( p, end, &len,
            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
        return( ret );

    if( *p + len != end )
        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );

    while( *p < end )
    {
        buf = &(cur->buf);
        buf->tag = **p;

        if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
            return( ret );

        buf->p = *p;
        *p += buf->len;

        /* Allocate and assign next pointer */
        if( *p < end )
        {
            cur->next = (asn1_sequence *) polarssl_malloc(
                 sizeof( asn1_sequence ) );

            if( cur->next == NULL )
                return( POLARSSL_ERR_ASN1_MALLOC_FAILED );

            cur = cur->next;
        }
    }

    /* Set final sequence entry's next pointer to NULL */
    cur->next = NULL;

    if( *p != end )
        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );

    return( 0 );
}
				

The above routine parses a sequence of ASN.1 variables from a X.509 certificate (starting a *p, ending at end). When the structure for the "cur->next" variable is allocated (line 32-33) it is NOT zero initialized but IS added to the result linked list (line 38). When an error in asn1_get_tag is triggered on the next iteration (line 23-24) the routine will return. The last "next" pointer of the resulting linked list is never initialized.

library/x509_crt.c:x509_crt_free

        seq_cur = cert_cur->ext_key_usage.next;
        while( seq_cur != NULL )
        {
            seq_prv = seq_cur;
            seq_cur = seq_cur->next;
            polarssl_zeroize( seq_prv, sizeof( x509_sequence ) );
            polarssl_free( seq_prv );
        }	
	

Upon freeing the X.509 certificate the parsed ASN.1 sequences are freed. This can bee seen in the code above. The linked list is iterated and every item is zeroed and de-allocated. Since the last "next" pointer is uninitialized this will zero and free an arbitrary memory location.

This vulnerability is exploitable [1,2] using (at least) two different methods. The "contents" of the uninitialized memory can directly be controlled by carefully manipulating the heap allocations. This in turn can be used to "zeroize" an arbitrary memory location and/or trigger a free() on an arbitrary memory location. This will lead to remote code execution and/or a denial of service.

References:

[1]: The poisoned NUL byte, 2014 edition

[2]: Understanding the heap by breaking it

Timeline

14-01-2015: Initial disclosure to whitehat@polarssl.org

14-01-2015: Feedback from PolarSSL received

15-01-2015: Disclosure timeline received from PolarSSL

16-01-2015: Informed NCSC-CERT of upcoming disclosure

19-01-2015: Public Disclosure

20-01-2015: Update with OpenVPN Connect and PowerDNS statements

20-01-2015: Include CVE number

Contact

Certified Secure

https://www.certifiedsecure.com

research@certifiedsecure.com

- Security is serious fun -