Android 4.3 KeyStore Stack Buffer Overflow

2014.07.03
Risk: Medium
Local: No
Remote: Yes
CWE: CWE-119


CVSS Base Score: 5.1/10
Impact Subscore: 6.4/10
Exploitability Subscore: 4.9/10
Exploit range: Remote
Attack complexity: High
Authentication: No required
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

The Vulnerability A stack buffer is created by the &#8216;KeyStore::getKeyForName&#8217; method. ResponseCode getKeyForName( Blob* keyBlob, const android::String8& keyName, const uid_t uid, const BlobType type) { char filename[NAME_MAX]; encode_key_for_uid(filename, uid, keyName); ... } ResponseCode getKeyForName( Blob* keyBlob, const android::String8& keyName, const uid_t uid, const BlobType type) { char filename[NAME_MAX]; encode_key_for_uid(filename, uid, keyName); ... } This function has several callers, which are accessible by external applications using the Binder interface (e.g., &#8216;android::KeyStoreProxy::get&#8217;). Therefore, the &#8216;keyName&#8217; variable can be controllable with an arbitrary size by a malicious application. As you can see, the &#8216;encode_key&#8217; routine that is called by &#8216;encode_key_for_uid&#8217; can overflow the &#8216;filename&#8217; buffer, since bounds checking is absent: C static int encode_key_for_uid( char* out, uid_t uid, const android::String8& keyName) { int n = snprintf(out, NAME_MAX, "%u_", uid); out += n; return n + encode_key(out, keyName); } static int encode_key( char* out, const android::String8& keyName) { const uint8_t* in = reinterpret_cast(keyName.string()); size_t length = keyName.length(); for (int i = length; i > 0; --i, ++in, ++out) { if (*in < '0' || *in > '~') { *out = '+' + (*in >> 6); *++out = '0' + (*in & 0x3F); ++length; } else { *out = *in; } } *out = ''; return length; } static int encode_key_for_uid( char* out, uid_t uid, const android::String8& keyName) { int n = snprintf(out, NAME_MAX, "%u_", uid); out += n; return n + encode_key(out, keyName); } static int encode_key( char* out, const android::String8& keyName) { const uint8_t* in = reinterpret_cast(keyName.string()); size_t length = keyName.length(); for (int i = length; i > 0; --i, ++in, ++out) { if (*in < '0' || *in > '~') { *out = '+' + (*in >> 6); *++out = '0' + (*in & 0x3F); ++length; } else { *out = *in; } } *out = ''; return length; } Exploitation Exploiting this vulnerability can theoretically be done by a malicious application; however, a working exploit needs to overcome a combination of obstacles: Data Execution Prevention (DEP). This can be bypassed by Return-Oriented Programming (ROP) payloads. Address Space Layout Randomization (ASLR) Stack Canaries Encoding. Characters below 030 (&#8217;0&#8242;) or above 0x7e (&#8216;~&#8217;) are encoded before being written on the buffer. However, the Android KeyStore is respawned every time it terminates. This behavior enables a probabilistic approach; moreover, the attacker may even theoretically abuse ASLR to defeat the encoding. Impact Successfully exploiting this vulnerability leads to a malicious code execution under the keystore process. Such code can: Leak the device&#8217;s lock credentials. Since the master key is derived by the lock credentials, whenever the device is unlocked, &#8216;Android::KeyStoreProxy::password&#8217; is called with the credentials. Leak decrypted master keys, data and hardware-backed key identifiers from the memory. Leak encrypted master keys, data and hardware-backed key identifiers from the disk for an offline attack. Interact with the hardware-backed storage and perform crypto operations (e.g., arbitrary data signing) on behalf of the user. Vulnerable Versions Android 4.3. Non-vulnerable Versions Android 4.4. Disclosure Timeline Jun. 23, 2014 Public disclosure. Nov. 11, 2013 Fix confirmed by Android Security Team. Oct. 22, 2013 Updates requested from Android Security Team. Sept. 9, 2013 Vulnerability acknowledged by Android Security Team. Sept. 9, 2013 Private disclosure to Android Security Team.

References:

http://securityintelligence.com/android-keystore-stack-buffer-overflow-to-keep-things-simple-buffers-are-always-larger-than-needed/#.U7TvEabWTGI


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top