-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

===========================================================================
             AUSCERT External Security Bulletin Redistribution

                               ESB-2018.2351
                    Multiple Smartcard Vulnerabilities
                              15 August 2018

===========================================================================

        AusCERT Security Bulletin Summary
        ---------------------------------

Product:           Smart card software
Publisher:         X41
Operating System:  Windows
                   Linux variants
                   OS X
Impact/Access:     Execute Arbitrary Code/Commands -- Console/Physical
                   Access Confidential Data        -- Console/Physical
Resolution:        Patch/Upgrade
CVE Names:         CVE-2018-14780 CVE-2018-14779 CVE-2018-4301
                   CVE-2018-4300  

Original Bulletin: 
   https://www.x41-dsec.de/lab/advisories/x41-2018-001-Yubico-Piv/
   https://www.x41-dsec.de/lab/advisories/x41-2018-002-OpenSC/
   https://www.x41-dsec.de/lab/advisories/x41-2018-003-pam_pkcs11/
   https://www.x41-dsec.de/lab/advisories/x41-2018-004-libykneomgr/
   https://www.x41-dsec.de/lab/advisories/x41-2018-005-smartcardservices/

Comment: This bulletin contains five (5) X41 security advisories.

- --------------------------BEGIN INCLUDED TEXT--------------------

X41 D-Sec GmbH Security Advisory: X41-2018-001

Multiple Vulnerabilities in Yubico Piv

Overview

Confirmed Affected Versions: 1.5.0

Confirmed Patched Versions: -

Vendor: Yubico

Vendor URL: https://www.yubico.com/

Credit: X41 D-Sec GmbH, Eric Sesterhenn

Status: Public

Advisory-URL: https://www.x41-dsec.de/lab/advisories/x41-2018-001-Yubico-Piv/

Summary and Impact

A buffer overflow and an out of bounds memory read were identified in the
yubico-piv-tool-1.5.0, these can be triggered by a malicious token.

X41 did not perform a full test or audit on the software.

Product Description

YubiKey 4, YubiKey 4 Nano, YubiKey 4C, YubiKey 4C Nano, and YubiKey NEO provide
Smart Card functionality based on the Personal Identity Verification (PIV)
interface specified in NIST SP 800-73, "Cryptographic Algorithms and Key Sizes
for PIV."

Out of Bounds Write via Malicious APDU

Severity Rating: High

Vector: APDU Response

CVE: CVE-2018-14779

CWE: 120

CVSS Score: 7.1 (High)

CVSS Vector: CVSS:3.0/AV:P/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

Summary and Impact

File lib/ykpiv.c contains the following code in function ykpiv_transfer_data()

    if(*out_len + recv_len - 2 > max_out) {
      fprintf(stderr, "Output buffer to small, wanted to write %lu, max was %lu.", *out_len + recv_len - 2, max_out);
    }
    if(out_data) {
      memcpy(out_data, data, recv_len - 2);
      out_data += recv_len - 2;
      *out_len += recv_len - 2;
    }

It is clearly checked whether the buffer is big enough to hold the data copied
using memcpy(), but no error handling happens to avoid the memcpy() in such
cases. This code path can be triggered with malicious data coming from a
smartcard.

Workarounds

None

Out of Bounds Read via malicious APDU

Severity Rating: LOW

Vector: APDU Response

CVE: CVE-2018-14780

CWE: 125

CVSS Score: 2.2 (Low)

CVSS Vector: CVSS:3.0/AV:P/AC:H/PR:N/UI:N/S:C/C:L/I:N/A:N

Summary and Impact

File lib/ykpiv.c contains the following code in function _ykpiv_fetch_object()

if(sw == SW_SUCCESS) {
  size_t outlen;
  int offs = _ykpiv_get_length(data + 1, &outlen);
  if(offs == 0) {
    return YKPIV_SIZE_ERROR;
  }
  memmove(data, data + 1 + offs, outlen);
  *len = outlen;
  return YKPIV_OK;
} else {
  return YKPIV_GENERIC_ERROR;
}

In the end, a memmove() occurs with a length retrieved from APDU data. This
length is not checked if it is outside of the APDU data retrieved. Therefore
the memmove() could copy bytes behind the allocated data buffer into this
buffer.

Workarounds

None

Timeline

2018-02-03 Issues found
2018-05-22 Vendor contacted
2018-05-22 Vendor reply
2018-06-05 Requesting technical feedback from the vendor
2018-06-06 Vendor confirms bug
2018-08-01 CVE ID requested
2018-08-02 CVE ID assigned
2018-08-08 Patched version released by vendor

Author: Eric Sesterhenn
Copyright (C) X41 D-SEC GmbH 2018

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

X41 D-Sec GmbH Security Advisory: X41-2018-002

Multiple Vulnerabilities in OpenSC

Overview

Confirmed Affected Versions: 0.17.0

Confirmed Patched Versions: -

Vendor: OpenSC

Vendor URL: https://github.com/OpenSC/OpenSC

Credit: X41 D-Sec GmbH, Eric Sesterhenn

Status: Public

Advisory-URL: https://www.x41-dsec.de/lab/advisories/x41-2018-002-OpenSC/

Summary and Impact

Multiple issues have been identified in OpenSC, ranging from stack based buffer
overflows to out of bounds reads and writes on the heap. They can be triggered
by malicious smartcards sending malformed responses to APDU commands.
Additionally to those fixes reported here, a lot of minor issues (eg. OOB reads
and similar) have been reported and fixed. The OpenSC team (especially Frank
Morgner) did an excellent job on identifying and fixing further issues.

Due to the large amount of issues, no individual issues have been rated with
CVSS / CVE ID yet.

X41 did not perform a full test or audit on the software, but tried to help
identifying as many bugs as possible in over the course of a year.

Product Description

OpenSC provides a set of libraries and utilities to work with smart cards. Its
main focus is on cards that support cryptographic operations, and facilitate
their use in security applications such as authentication, mail encryption and
digital signatures.

OOB Write in muscle_list_files()

In funcion muscle_list_files() in file src/libopensc/card-muscle.c an out of
bounds write might occur, since bufLen is not checked.

static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
{
        muscle_private_t* priv = MUSCLE_DATA(card);
        mscfs_t *fs = priv->fs;
        int x;
        int count = 0;

        mscfs_check_cache(priv->fs);

        for(x = 0; x < fs->cache.size; x++) {
                u8* oid= fs->cache.array[x].objectId.id;
                sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
                        "FILE: %02X%02X%02X%02X\n",
                        oid[0],oid[1],oid[2],oid[3]);
                if(0 == memcmp(fs->currentPath, oid, 2)) {
                        buf[0] = oid[2];
                        buf[1] = oid[3];
                        if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */
                        buf += 2;
                        count+=2;
                }
        }
        return count;
}

OOB Write in tcos_select_file()

In function tcos_select_file) in file src/libopensc/card-tcos.c a filename is
extracted from an APDU response and written into the internal file->name
variable.

                case 0x84:
                        memcpy(file->name, d, len);
                        file->namelen = len;
                        break;

No check is performed whether the string retrieved from the card fits into the
buffer, which could trigger an OOB write.

OOB Write in piv_validate_general_authentication()

In case piv_validate_general_authentication()in src/libopensc/card-piv.c is
called with a datalen parameter greater than 4096, an out of bound write
occurs. Currently no caller seems to do this.

OOB Write in gemsafe_get_cert_len()

The function gemsafe_get_cert_len() in file src/libopensc/pkcs15-gemsafeV1.c
might write beyond the gemsafe_prkeys and gemsafe_cert arrays in case more than
12 containers are stored on the card.

        ind = 2; /* skip length */
        while (ibuf[ind] == 0x01) {
                if (ibuf[ind+1] == 0xFE) {
                        gemsafe_prkeys[i].ref = ibuf[ind+4];
                        sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",
                                        i+1, gemsafe_prkeys[i].ref);
                        ind += 9;
                }
                else {
                        gemsafe_prkeys[i].label = NULL;
                        gemsafe_cert[i].label = NULL;
                        sc_log(card->ctx, "Key container %d is unallocated", i+1);
                        ind += 8;
                }
                i++;
        }

OOB Write in util_acl_to_str()

In function util_acl_to_str() in file src/tools/util.c no checks are performed
whether the string put together fits into line, which could be abused to
trigger limited out of bounds writes.

OOB Write in read_public_key() and read_private_key()

In function read_public_key() in file src/tools/cryptoflex-tool.c the bufsize
variable is overwritten with file->size retrieved from the smartcard. This
could be bigger than 2048, allowing for a stack based buffer overflow in the
sc_read_binary() call.

        u8 buf[2048], *p = buf;
        size_t bufsize, keysize;

        r = select_app_df();
        if (r)
                return 1;
        sc_format_path("I1012", &path);
        r = sc_select_file(card, &path, &file);
        if (r) {
                fprintf(stderr, "Unable to select public key file: %s\n", sc_strerror(r));
                return 2;
        }
        bufsize = file->size;
        sc_file_free(file);
        r = sc_read_binary(card, 0, buf, bufsize, 0);

The same issue can be found in read_private_key()

        bufsize = file->size;
        sc_file_free(file);
        r = sc_read_binary(card, 0, buf, bufsize, 0);

OOB Write in decrypt_response()

In function decrypt_response() in file src/libopensc/card-epass2003.c an out of
bounds overwrite can occur. No check is performed if the plaintext buffer fits
into the out buffer before copying, leading to a memory overwrite.

        memcpy(out, plaintext, in_len - 2);
        *out_len = in_len - 2;
        return 0;

OOB Write in cac_get_serial_nr_from_CUID()

In function cac_get_serial_nr_from_CUID() in file src/libopensc/card-cac.c a
serial number is copied into serial->value. The length argument of the memcpy()
is the length of the source, not the destination, which can lead to an out of
bounds memory write.

        if (priv->cac_id_len) {
                serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR);
                memcpy(serial->value, priv->cac_id, priv->cac_id_len);
                SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
        }

Off by One Write in sc_pkcs15emu_esteid_init()

In function sc_pkcs15emu_esteid_init() in file src/libopensc/pkcs15-esteid.c an
off by one write with a \x00 occurs in case the sc_read_record() functions
returns sizeof(buf) read bytes.

        /* read the serial (document number) */
        r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
        SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed");
        buff[r] = '\0';

Double Free in sc_file_set_sec_attr()

In function sc_file_set_sec_attr() in file src/libopensc/sc.c a double free
occurs in case sec_attr_len is equal to 0, since the call to realloc() will
free file->sec_attr and return NULL. The variable is then freed again in the
error handling path.

        tmp = (u8 *) realloc(file->sec_attr, sec_attr_len);
        if (!tmp) {
                if (file->sec_attr)
                        free(file->sec_attr);
                file->sec_attr     = NULL;
                file->sec_attr_len = 0;
                return SC_ERROR_OUT_OF_MEMORY;
        }

Double Free in read_file()

In function read_file() in file src/tools/egk-tool.c a double free can be
triggered in case two calls to sc_select_file() return a file->size of zero.
The first call to realloc() frees the memory, the second frees it again.

        len = file - file->size : 4096;
        p = realloc(*data, len);
        if (!p) {
                goto err;
        }

It is clearly checked whether the buffer is big enough to hold the data copied
using memcpy(), but no error handling happens to avoid the memcpy() in such
cases. This code path can be triggered with malicious data coming from a
smartcard.

Double free in sc_pkcs15emu_sc_hsm_init()

In function sc_pkcs15emu_sc_hsm_init() in file src/libopensc/pkcs15-sc-hsm.c a
double free can occur, since this function can be called twice. The call to
realloc() with a size of 0 would free priv->EF_C_DevAut with a second call
freeing the already freed memory.

                /* save EF_C_DevAut for further use */
                ptr = realloc(priv->EF_C_DevAut, len);
                if (ptr) {
                        memcpy(ptr, efbin, len);
                        priv->EF_C_DevAut = ptr;
                        priv->EF_C_DevAut_len = len;
                }

                ptr = efbin;

Unbound Recursion in iasecc_select_mf()/iasecc_select_file()

Function iasecc_select_file() in file src/libopensc/card-iasecc.c calls
iasecc_select_mf() in the same file, which calls iasecc_select_file() again.
This can lead to an infinite recursion exhausting the stack.

Timeline

2018-02-03 Issues found
2018-04-18 Vendor contacted
2018-04-18 Vendor reply
2018-05-18 Technical details provided
2018-05-24 Private git branch created, fixing started
2018-08-11 Patched version released: https://github.com/x41sec/OpenSC

Author: Eric Sesterhenn
Copyright (C) X41 D-SEC GmbH 2018

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

X41 D-Sec GmbH Security Advisory: X41-2018-002

Multiple Vulnerabilities in OpenSC

Overview

Confirmed Affected Versions: 0.17.0

Confirmed Patched Versions: -

Vendor: OpenSC

Vendor URL: https://github.com/OpenSC/OpenSC

Credit: X41 D-Sec GmbH, Eric Sesterhenn

Status: Public

Advisory-URL: https://www.x41-dsec.de/lab/advisories/x41-2018-002-OpenSC/

Summary and Impact

Multiple issues have been identified in OpenSC, ranging from stack based buffer
overflows to out of bounds reads and writes on the heap. They can be triggered
by malicious smartcards sending malformed responses to APDU commands.
Additionally to those fixes reported here, a lot of minor issues (eg. OOB reads
and similar) have been reported and fixed. The OpenSC team (especially Frank
Morgner) did an excellent job on identifying and fixing further issues.

Due to the large amount of issues, no individual issues have been rated with
CVSS / CVE ID yet.

X41 did not perform a full test or audit on the software, but tried to help
identifying as many bugs as possible in over the course of a year.

Product Description

OpenSC provides a set of libraries and utilities to work with smart cards. Its
main focus is on cards that support cryptographic operations, and facilitate
their use in security applications such as authentication, mail encryption and
digital signatures.

OOB Write in muscle_list_files()

In funcion muscle_list_files() in file src/libopensc/card-muscle.c an out of
bounds write might occur, since bufLen is not checked.

static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
{
        muscle_private_t* priv = MUSCLE_DATA(card);
        mscfs_t *fs = priv->fs;
        int x;
        int count = 0;

        mscfs_check_cache(priv->fs);

        for(x = 0; x < fs->cache.size; x++) {
                u8* oid= fs->cache.array[x].objectId.id;
                sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
                        "FILE: %02X%02X%02X%02X\n",
                        oid[0],oid[1],oid[2],oid[3]);
                if(0 == memcmp(fs->currentPath, oid, 2)) {
                        buf[0] = oid[2];
                        buf[1] = oid[3];
                        if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */
                        buf += 2;
                        count+=2;
                }
        }
        return count;
}

OOB Write in tcos_select_file()

In function tcos_select_file) in file src/libopensc/card-tcos.c a filename is
extracted from an APDU response and written into the internal file->name
variable.

                case 0x84:
                        memcpy(file->name, d, len);
                        file->namelen = len;
                        break;

No check is performed whether the string retrieved from the card fits into the
buffer, which could trigger an OOB write.

OOB Write in piv_validate_general_authentication()

In case piv_validate_general_authentication()in src/libopensc/card-piv.c is
called with a datalen parameter greater than 4096, an out of bound write
occurs. Currently no caller seems to do this.

OOB Write in gemsafe_get_cert_len()

The function gemsafe_get_cert_len() in file src/libopensc/pkcs15-gemsafeV1.c
might write beyond the gemsafe_prkeys and gemsafe_cert arrays in case more than
12 containers are stored on the card.

        ind = 2; /* skip length */
        while (ibuf[ind] == 0x01) {
                if (ibuf[ind+1] == 0xFE) {
                        gemsafe_prkeys[i].ref = ibuf[ind+4];
                        sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",
                                        i+1, gemsafe_prkeys[i].ref);
                        ind += 9;
                }
                else {
                        gemsafe_prkeys[i].label = NULL;
                        gemsafe_cert[i].label = NULL;
                        sc_log(card->ctx, "Key container %d is unallocated", i+1);
                        ind += 8;
                }
                i++;
        }

OOB Write in util_acl_to_str()

In function util_acl_to_str() in file src/tools/util.c no checks are performed
whether the string put together fits into line, which could be abused to
trigger limited out of bounds writes.

OOB Write in read_public_key() and read_private_key()

In function read_public_key() in file src/tools/cryptoflex-tool.c the bufsize
variable is overwritten with file->size retrieved from the smartcard. This
could be bigger than 2048, allowing for a stack based buffer overflow in the
sc_read_binary() call.

        u8 buf[2048], *p = buf;
        size_t bufsize, keysize;

        r = select_app_df();
        if (r)
                return 1;
        sc_format_path("I1012", &path);
        r = sc_select_file(card, &path, &file);
        if (r) {
                fprintf(stderr, "Unable to select public key file: %s\n", sc_strerror(r));
                return 2;
        }
        bufsize = file->size;
        sc_file_free(file);
        r = sc_read_binary(card, 0, buf, bufsize, 0);

The same issue can be found in read_private_key()

        bufsize = file->size;
        sc_file_free(file);
        r = sc_read_binary(card, 0, buf, bufsize, 0);

OOB Write in decrypt_response()

In function decrypt_response() in file src/libopensc/card-epass2003.c an out of
bounds overwrite can occur. No check is performed if the plaintext buffer fits
into the out buffer before copying, leading to a memory overwrite.

        memcpy(out, plaintext, in_len - 2);
        *out_len = in_len - 2;
        return 0;

OOB Write in cac_get_serial_nr_from_CUID()

In function cac_get_serial_nr_from_CUID() in file src/libopensc/card-cac.c a
serial number is copied into serial->value. The length argument of the memcpy()
is the length of the source, not the destination, which can lead to an out of
bounds memory write.

        if (priv->cac_id_len) {
                serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR);
                memcpy(serial->value, priv->cac_id, priv->cac_id_len);
                SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
        }

Off by One Write in sc_pkcs15emu_esteid_init()

In function sc_pkcs15emu_esteid_init() in file src/libopensc/pkcs15-esteid.c an
off by one write with a \x00 occurs in case the sc_read_record() functions
returns sizeof(buf) read bytes.

        /* read the serial (document number) */
        r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
        SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed");
        buff[r] = '\0';

Double Free in sc_file_set_sec_attr()

In function sc_file_set_sec_attr() in file src/libopensc/sc.c a double free
occurs in case sec_attr_len is equal to 0, since the call to realloc() will
free file->sec_attr and return NULL. The variable is then freed again in the
error handling path.

        tmp = (u8 *) realloc(file->sec_attr, sec_attr_len);
        if (!tmp) {
                if (file->sec_attr)
                        free(file->sec_attr);
                file->sec_attr     = NULL;
                file->sec_attr_len = 0;
                return SC_ERROR_OUT_OF_MEMORY;
        }

Double Free in read_file()

In function read_file() in file src/tools/egk-tool.c a double free can be
triggered in case two calls to sc_select_file() return a file->size of zero.
The first call to realloc() frees the memory, the second frees it again.

        len = file - file->size : 4096;
        p = realloc(*data, len);
        if (!p) {
                goto err;
        }

It is clearly checked whether the buffer is big enough to hold the data copied
using memcpy(), but no error handling happens to avoid the memcpy() in such
cases. This code path can be triggered with malicious data coming from a
smartcard.

Double free in sc_pkcs15emu_sc_hsm_init()

In function sc_pkcs15emu_sc_hsm_init() in file src/libopensc/pkcs15-sc-hsm.c a
double free can occur, since this function can be called twice. The call to
realloc() with a size of 0 would free priv->EF_C_DevAut with a second call
freeing the already freed memory.

                /* save EF_C_DevAut for further use */
                ptr = realloc(priv->EF_C_DevAut, len);
                if (ptr) {
                        memcpy(ptr, efbin, len);
                        priv->EF_C_DevAut = ptr;
                        priv->EF_C_DevAut_len = len;
                }

                ptr = efbin;

Unbound Recursion in iasecc_select_mf()/iasecc_select_file()

Function iasecc_select_file() in file src/libopensc/card-iasecc.c calls
iasecc_select_mf() in the same file, which calls iasecc_select_file() again.
This can lead to an infinite recursion exhausting the stack.

Timeline

2018-02-03 Issues found
2018-04-18 Vendor contacted
2018-04-18 Vendor reply
2018-05-18 Technical details provided
2018-05-24 Private git branch created, fixing started
2018-08-11 Patched version released: https://github.com/x41sec/OpenSC

Author: Eric Sesterhenn
Copyright (C) X41 D-SEC GmbH 2018

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

X41 D-Sec GmbH Security Advisory: X41-2018-004

Multiple Vulnerabilities in Yubico libykneomgr

Overview

Confirmed Affected Versions: 0.1.9

Confirmed Patched Versions: -

Vendor: Yubico / Depreciated

Vendor URL: https://www.yubico.com/

Credit: X41 D-Sec GmbH, Eric Sesterhenn

Status: Public

Advisory-URL: https://www.x41-dsec.de/lab/advisories/x41-2018-004-libykneomgr/

Summary and Impact

An out of bounds write and read was discovered when malicious responses from a
smartcard are received. These might lead to memory corruptions. We assume that
these are not easily exploitable. X41 did not perform a full test or audit on
the software. Please note that the library is deprecated for more than a year
and no update will be published by the vendor.

Product Description

This is a C library to interact with the CCID-part of the YubiKey NEO. There is
a command line tool "ykneomgr" for interactive use. It supports querying the
YubiKey NEO for firmware version, operation mode (OTP/CCID) and serial number.
You may also mode switch the device and manage applets (list, delete and
install).

Out of Bounds Read/Writes

Severity Rating: Medium

Vector: APDU Response

CVE:

CWE: 120

CVSS Score: 7.1 (High)

CVSS Vector: CVSS:3.0/AV:P/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

Summary and Impact

File lib/backend_pcsc.c contains the following code in function
backend_applet_list()

     {
       size_t i;
       size_t this_len = recv[length++];

       for (i = 0; i < this_len; i++)
        {
          if (appletstr)
            {
             if (real_len + 2 > *len)
                {
                  return YKNEOMGR_BACKEND_ERROR;
                }
              sprintf (p, "%02x", recv[length]);
              p += 2;
            }
          real_len += 2;
          length++;
        }
      if (appletstr)
        {
          if (real_len + 1 > *len)
            {
              return YKNEOMGR_BACKEND_ERROR;
            }
          *p = '\0';
          p++;
        }
      real_len++;
      length += 2;
    }

There is an off-by-one write of a '\x00' when the sprintf() is called, since it
terminates the string with a trailing null-byte. Additionally reads are
performed based on this_len, which is retrieved from the data without further
safety checks.

Workarounds

It is advised to migrate to YubiKey Manager since the vendor does not support
the library anymore and will not issue a patch.

Timeline

2018-02-03 Issues found
2018-05-22 Vendor contacted
2018-05-22 Vendor reply
2018-06-05 Requesting technical feedback from the vendor
2018-06-06 Vendor confirms bug, but states that library is depreciated, will
not be fixed

Author: Eric Sesterhenn
Copyright (C) X41 D-SEC GmbH 2018

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

X41 D-Sec GmbH Security Advisory: X41-2018-005

Multiple Vulnerabilities in Apple smartcardservices

Overview

Confirmed Affected Versions: e3eb96a6eff9d02497a51b3c155a10fa5989021f

Confirmed Patched Versions: 8eef01a5e218ae78cc358de32213b50a601662de

Vendor: Apple

Vendor URL: https://smartcardservices.github.io/

Credit: X41 D-Sec GmbH, Eric Sesterhenn

Status: Public

Advisory-URL: https://www.x41-dsec.de/lab/advisories/
x41-2018-005-smartcardservices/

Summary and Impact

Attackers with local access can exploit security issues in the smartcard
driver. These result in memory corruptions, which might lead to code execution.
Since smartcards can be used for authentication, the vulnerabilities may allow
an attacker to login to the system without valid credentials as any user.

X41 did not perform a full test or audit on the software.

Product Description

The Smart Card Services project is comprised of several components which, when
combined, provide the necessary abstraction layer and integration of smart
cards into Apple's CDSA implementation.

Stack based buffer overflow

Severity Rating: Medium

Vector: APDU Response

CVE: CVE-2018-4300

CWE: 120

CVSS Score: 7.1 (High)

CVSS Vector: CVSS:3.0/AV:P/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

Summary and Impact

In file Tokend/CAC/CACRecord.cpp the function
CACCertificateRecord::getDataAttribute() might overwrite the value certificate
and possibly other stack data, if a smartcard provides malicious data.

        unsigned char command[] = { 0x80, 0x36, 0x00, 0x00, 0x64 };
        unsigned char result[MAX_BUFFER_SIZE];
        size_t resultLength = sizeof(result);
        uint8 certificate[CAC_MAXSIZE_CERT];
        uint8 uncompressed[CAC_MAXSIZE_CERT];
        size_t certificateLength = 0;

        try
        {
                PCSC::Transaction _(cacToken);
                cacToken.select(mApplication);
                uint32_t cacreturn;
                do
                {
                        cacreturn = cacToken.exchangeAPDU(command, sizeof(command), result,
                                resultLength);

                        if ((cacreturn & 0xFF00) != 0x6300)
                                CACError::check(cacreturn);

                        size_t requested = command[4];
                        if (resultLength != requested + 2)
                PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);

                        memcpy(certificate + certificateLength, result, resultLength - 2);
                        certificateLength += resultLength - 2;
                        // Number of bytes to fetch next time around is in the last byte
                        // returned.
                        command[4] = cacreturn & 0xFF;
                } while ((cacreturn & 0xFF00) == 0x6300);
        }
        catch (...)
        {
                return NULL;
        }

As long as the smartcard returns a return code of 0x63FF, more data is copied
into the certificate buffer, causing a stack based overflow. A malicious
smartcard is able to control all of the overflowed bytes.

Workarounds

None

Stack based buffer overflow with limited input

Severity Rating: Medium

Vector: APDU Response

CVE: CVE-2018-4301

CWE: 120

CVSS Score: 7.1 (High)

CVSS Vector: CVSS:3.0/AV:P/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H

Summary and Impact

In file Tokend/PKCS11/GemaltoKeyHandle.cpp the function
GemaltoPrivateKeyRecord::computeDecrypt() might overwrite the value strData if
the supplied dataLength is too big.

void GemaltoPrivateKeyRecord::computeDecrypt(GemaltoToken &gemaltoToken, CK_ULONG mech, const AccessCredentials *cred, unsigned char *data, size_t dataLength, unsigned char *output, size_t &outputLength)
{
        GemaltoToken::log("\nGemaltoPrivateKeyRecord::computeDecrypt <BEGIN>\n");
        GemaltoToken::log("GemaltoPrivateKeyRecord::computeDecrypt - mechanism <%lu>\n", mech);
        GemaltoToken::log("GemaltoPrivateKeyRecord::computeDecrypt - cred <%p>\n", cred);
        char strData[6000];
        memset(strData, '\0', sizeof(strData));
        char* str = strData;
        for (size_t i=0; i<dataLength; i++)
        {
                str += sprintf(str, "%02x ", data[i]);
        }
        GemaltoToken::log("GemaltoPrivateKeyRecord::computeDecrypt - dataLength <%lu> - data <%s>\n", dataLength, strData);
        GemaltoToken::log("GemaltoPrivateKeyRecord::computeDecrypt - output <%p>\n", output);
        GemaltoToken::log("GemaltoPrivateKeyRecord::computeDecrypt - outputLength <%lu>\n", outputLength);

The attacker might control the data which is to be decrypted, but exploitation
is limited by the sprintf() format string.

Workarounds

None

Timeline

2018-02-03 Issues found
2018-05-22 Vendor contacted
2018-05-22 Automated vendor reply
2018-05-23 Personal vendor reply
2018-06-05 Requesting technical feedback from the vendor
2018-06-22 Vendor states that the bugs are fixed in public git
2018-07-12 CVE IDs assigned
2018-08-03 https://smartcardservices.github.io/security/ updated

Author: Eric Sesterhenn
Copyright (C) X41 D-SEC GmbH 2018

- --------------------------END INCLUDED TEXT--------------------

You have received this e-mail bulletin as a result of your organisation's
registration with AusCERT. The mailing list you are subscribed to is
maintained within your organisation, so if you do not wish to continue
receiving these bulletins you should contact your local IT manager. If
you do not know who that is, please send an email to auscert@auscert.org.au
and we will forward your request to the appropriate person.

NOTE: Third Party Rights
This security bulletin is provided as a service to AusCERT's members.  As
AusCERT did not write the document quoted above, AusCERT has had no control
over its content. The decision to follow or act on information or advice
contained in this security bulletin is the responsibility of each user or
organisation, and should be considered in accordance with your organisation's
site policies and procedures. AusCERT takes no responsibility for consequences
which may arise from following or acting on information or advice contained in
this security bulletin.

NOTE: This is only the original release of the security bulletin.  It may
not be updated when updates to the original are made.  If downloading at
a later date, it is recommended that the bulletin is retrieved directly
from the author's website to ensure that the information is still current.

Contact information for the authors of the original document is included
in the Security Bulletin above.  If you have any questions or need further
information, please contact them directly.

Previous advisories and external security bulletins can be retrieved from:

        https://www.auscert.org.au/bulletins/

===========================================================================
Australian Computer Emergency Response Team
The University of Queensland
Brisbane
Qld 4072

Internet Email: auscert@auscert.org.au
Facsimile:      (07) 3365 7031
Telephone:      (07) 3365 4417 (International: +61 7 3365 4417)
                AusCERT personnel answer during Queensland business hours
                which are GMT+10:00 (AEST).
                On call after hours for member emergencies only.
===========================================================================
-----BEGIN PGP SIGNATURE-----
Comment: http://www.auscert.org.au/render.html?it=1967

iQIVAwUBW3Oww2aOgq3Tt24GAQi5ig/7BY5I+s+NgCKcOd0XnXLqU+a5qC5c1zW9
4Zt9PMnRJS3+68B/toAmF11chjIPAv5BsoFoxUvFUKJb6hRJl77msdXWz4XiE1Ip
F3kwcxut0cxykYjAv/Ilc5s6MTIrnaKhOuouKRACpvA8oDoNNl2CTpeKOmHC1rLM
XsRnKiBxc0qhblhF4ZmWaW89TY+mSL39JQDb7CIBPhKPnIZ4OKDk0FpYX4CPYaSu
YIgZ4x+J+Vj2SF9Mt/TL2vcJMl2NXeEGB+UEQHSWkRqUkM9k4kXKDk4oHn2i6D3c
XCm87j3HEE8GfWLzru9P5Fnuk6wfbbRJEnxu3ctJHN2jR4emLt+9/Ax4GrZC2FPY
cty4YfdTICmpHkSLbPTKE6KBC4WK4M87SWEP+Lfu0D7du7YvOVCV+PQcOKGGChrw
8SC+CIwiE9Rlx4F/tf//HYgypV3i1UX9POeK4DzZRZgQrHKN6HdRAn2zhGPIaXf5
NC/ck9wtkAvs7x4y10qxpQpy2sthJUTdhxRVGpxg9WzgIo51ZIxB57SJa8F9VT1o
FLaun2w0ZwINJ8sT4rjRuH/jcMVQAm9tyYqBfVDNjOeJduIHh3/yw/JAo6yvJqvn
Deon/oIbawtNdwnC6nuXPLMebkg7/aKMz3CUTpY1M8hgNXeDTmdVrKFcWdqNxFUt
S7OCLfjWKH4=
=U3EO
-----END PGP SIGNATURE-----