
1979 changes to exploits/shellcodes Couchdb 1.5.0 - 'uuids' Denial of Service Apache CouchDB 1.5.0 - 'uuids' Denial of Service Beyond Remote 2.2.5.3 - Denial of Service (PoC) udisks2 2.8.0 - Denial of Service (PoC) Termite 3.4 - Denial of Service (PoC) SoftX FTP Client 3.3 - Denial of Service (PoC) Silverstripe 2.3.5 - Cross-Site Request Forgery / Open redirection SilverStripe CMS 2.3.5 - Cross-Site Request Forgery / Open Redirection Silverstripe CMS 3.0.2 - Multiple Vulnerabilities SilverStripe CMS 3.0.2 - Multiple Vulnerabilities Silverstripe CMS 2.4 - File Renaming Security Bypass SilverStripe CMS 2.4 - File Renaming Security Bypass Silverstripe CMS 2.4.5 - Multiple Cross-Site Scripting Vulnerabilities SilverStripe CMS 2.4.5 - Multiple Cross-Site Scripting Vulnerabilities Silverstripe CMS 2.4.7 - 'install.php' PHP Code Injection SilverStripe CMS 2.4.7 - 'install.php' PHP Code Injection Silverstripe Pixlr Image Editor - 'upload.php' Arbitrary File Upload SilverStripe CMS Pixlr Image Editor - 'upload.php' Arbitrary File Upload Silverstripe CMS 2.4.x - 'BackURL' Open Redirection SilverStripe CMS 2.4.x - 'BackURL' Open Redirection Silverstripe CMS - 'MemberLoginForm.php' Information Disclosure SilverStripe CMS - 'MemberLoginForm.php' Information Disclosure Silverstripe CMS - Multiple HTML Injection Vulnerabilities SilverStripe CMS - Multiple HTML Injection Vulnerabilities Apache CouchDB 1.7.0 and 2.x before 2.1.1 - Remote Privilege Escalation Apache CouchDB 1.7.0 / 2.x < 2.1.1 - Remote Privilege Escalation Monstra CMS before 3.0.4 - Cross-Site Scripting Monstra CMS < 3.0.4 - Cross-Site Scripting (2) Monstra CMS < 3.0.4 - Cross-Site Scripting Monstra CMS < 3.0.4 - Cross-Site Scripting (1) Navigate CMS 2.8 - Cross-Site Scripting Collectric CMU 1.0 - 'lang' SQL injection Joomla! Component CW Article Attachments 1.0.6 - 'id' SQL Injection LG SuperSign EZ CMS 2.5 - Remote Code Execution MyBB Visual Editor 1.8.18 - Cross-Site Scripting Joomla! Component AMGallery 1.2.3 - 'filter_category_id' SQL Injection Joomla! Component Micro Deal Factory 2.4.0 - 'id' SQL Injection RICOH Aficio MP 301 Printer - Cross-Site Scripting Joomla! Component Auction Factory 4.5.5 - 'filter_order' SQL Injection RICOH MP C6003 Printer - Cross-Site Scripting Linux/ARM - Egghunter (PWN!) + execve(_/bin/sh__ NULL_ NULL) Shellcode (28 Bytes) Linux/ARM - sigaction() Based Egghunter (PWN!) + execve(_/bin/sh__ NULL_ NULL) Shellcode (52 Bytes)
63 lines
No EOL
5.6 KiB
Text
63 lines
No EOL
5.6 KiB
Text
The keystore binder service ("android.security.IKeystoreService") allows users to issue several commands related to key management, including adding, removing, exporting and generating cryptographic keys. The service is accessible to many SELinux contexts, including application contexts, but also unprivileged daemons such as "media.codec".
|
|
|
|
Binder calls to this service are unpacked by IKeyStoreService (http://androidxref.com/8.0.0_r4/xref/system/security/keystore/IKeystoreService.cpp), and are then passed on to be processed by KeyStoreService. The "generateKey" command is handled by "KeyStoreService::generateKey" (http://androidxref.com/8.0.0_r4/xref/system/security/keystore/key_store_service.cpp#691). Here is a snippet from this function:
|
|
|
|
1. KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
|
|
2. const hidl_vec<KeyParameter>& params,
|
|
3. const hidl_vec<uint8_t>& entropy, int uid,
|
|
4. int flags,
|
|
5. KeyCharacteristics* outCharacteristics) {
|
|
6. uid = getEffectiveUid(uid);
|
|
7. KeyStoreServiceReturnCode rc =
|
|
8. checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
|
|
9. if (!rc.isOk()) {
|
|
10. return rc;
|
|
11. }
|
|
12. if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
|
|
13. ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
|
|
14. return ResponseCode::PERMISSION_DENIED;
|
|
15. }
|
|
16.
|
|
17. if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
|
|
18. if (!checkBinderPermission(P_GEN_UNIQUE_ID)) return ResponseCode::PERMISSION_DENIED;
|
|
19. }
|
|
20. ...
|
|
21. }
|
|
|
|
Like most KeyStore calls, this method uses "KeyStoreService::checkBinderPermission" in order to validate the calling process's permissions. This function uses a twofold approach to verify the caller (http://androidxref.com/8.0.0_r4/xref/system/security/keystore/key_store_service.cpp#checkBinderPermission):
|
|
|
|
1. The caller's UID is retrieved using IPCThreadState::self()->getCallingUid() and compared against an array of pre-populated UIDs and permissions ("user_perms")
|
|
1.1 If the UID matches any in the array, its permission set is retrieved from the array
|
|
1.2 If the UID isn't in the array, the default permission set is used ("DEFAULT_PERMS")
|
|
2. The caller's SELinux context is retrieved using getpidcon(...) using the PID from the binder transaction (IPCThreadState::self()->getCallingPid())
|
|
2.1 An SELinux access check is performed for the given context and operation
|
|
|
|
Specifically to our case, if a "generateKey" command is called with a "INCLUDE_UNIQUE_ID" tag, the KeyStore will use an attestation certificate for the generated key with an application-scoped and time-bounded device-unique ID. Since creating attestation keys is a privileged operation, it should not be carried out by any user.
|
|
|
|
This restriction is enforced using the SELinux context enforcement alone -- the "default" permission set ("DEFAULT_PERMS") contains the aforementioned permission:
|
|
|
|
static const perm_t DEFAULT_PERMS = static_cast<perm_t>(
|
|
P_GET_STATE | P_GET | P_INSERT | P_DELETE | P_EXIST | P_LIST | P_SIGN | P_VERIFY |
|
|
P_GEN_UNIQUE_ID /* Only privileged apps can do this, but enforcement is done by SELinux */);
|
|
|
|
As noted in the comment above, this API is restricted to "priv_app" SELinux contexts, which is enforced using validation #2 above.
|
|
|
|
However, using the calling PID in order to enforce access controls in binder calls is an invalid approach. This is since the calling PID can transition from zombie to dead, allowing other PIDs to take its place. Therefore, the following attack flow is possible:
|
|
|
|
1. Process A forks and creates process B
|
|
2. Process A cycles pids until it reaches the pid before its own
|
|
3. Process B issues a binder transaction for the KeyStore service, containing an INCLUDE_UNIQUE_ID tag
|
|
4. Process A kills process B, allowing it to transition to dead
|
|
5. Process A spawns a new "priv_app" instance, occupying process B's PID
|
|
|
|
If points 4-5 are completed before the KeyStore service performs the "getpidcon" call, the permission check will use the new app's SELinux context, allowing the access control checks to pass. Otherwise, since no ill effects happen if the race fails, an attacker can continue issuing calls until the race succeeds.
|
|
|
|
As for spawning a new "priv_app" instance, this can be achieved by issuing a query request to a content provider published by a "priv_app". Many such providers exist (the contacts provider, telephony provider, settings provider, etc.). In this case, I chose to use the "calendar" provider, as it was not running on the device to begin with (and is therefore had to be spawned in order to handle the query request).
|
|
|
|
In order to expand the timing window for the PoC, I've added a "sleep" call to the KeyStore service's "generateKey" call. You can find the patch under "keystore.diff".
|
|
|
|
After applying the patch, the attached PoC should be built as part of the Android source tree, by extracting the source files into "frameworks/native/cmds/keystorerace", and running a build (e.g., "mmm keystorerace"). The resulting binary ("keystorerace") contains the PoC code. Running it should result in a new device-unique key being generated, despite not being executed from a "priv_app".
|
|
|
|
|
|
Proof of Concept:
|
|
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/43996.zip |