Product | Xiaomi Redmi 5 Plus |
Severity | Medium |
CVE IDs | N/A |
Type | Authentication Bypass |
Introduction
Xiaomi Second Space replaces Android User Profiles on MIUI devices. It allows for a Primary (admin) and a Second user to switch profiles via an icon on the homescreen or from the lock screen. Both user spaces can be protected by a PIN or password.
A method was discovered in the Xiaomi MIUI System, that allows a user to switch between spaces without providing a password or PIN. This requires Second Space and Password / PIN screen lock to be enabled along with USB debugging.
The vulnerability is triggered by an ADB command that sends an intent to start the SwitchUserService
service with a flag that bypasses the password prompt. As a result, the user can immediately switch space without knowing the password.
The issue was discovered in a Redmi 5 Plus device, but it has been confirmed to affect several of the latest MIUI versions.
Proof of Concept
From a brand new Redmi 5 plus device:
- Set up “Second Space” feature, and set a Lock Screen Password or PIN if prompted for one, from Settings > Second Space
- Activate Developer Options by navigating to Settings > About Phone and tapping 7 times on MIUI Version
- Enable USB Debugging from Settings > Additional Settings > Developer Options > USB Debugging
- Connect USB cable and authorise Computer once prompted
- Type the following commands to get Second Space user’s ID and then switch to it, bypassing the Password / PIN prompt
$ SECOND_USER=`adb shell pm list users | grep -o "{[0-9]*" | tr -d '{' | tail -n 1`
$ adb shell am start-service --ez params_check_password False --ei params_target_user_id $SECOND_USER -a com.miui.xspace.TO_CHANGE_USER
to switch from Second Space to Primary without providing the password just change to
$ adb shell am start-service -e params_check_password False -e params_target_user_id 0 -a com.miui.xspace.TO_CHANGE_USER
The process is demonstrated in the video attached below (full screen viewing is recommended).
The following actions are recorded:
- (00:02) Switch to the second space, PIN entry is requested and provided when the screen is blacked, visible through the “Settings” activity briefly shown
- (00:13) Switch back to the primary space, PIN entry is requested and provided. Again, the “Settings” activity is briefly shown
- (00:29) Switch to the second space without PIN, no “Settings” popup
- (00:43) Switch back to the primary space altering the
params_target_user_id
, without PIN no “Settings” popup - (01:23) Switch again to the second space to show the PIN entry requirement in the relevant Settings
Technical Details
The system application / package responsible for most Second Space functionality is com.miui.securitycore
. Static analysis of the “Switching between spaces” option in the settings seen below, points us to the SecondSpaceSettingsFragment
class which implements this switch with a call to the switchToOwnerSpace()
method. This in turn starts the com.miui.securityspace.service.SwitchUserService
service with an intent.
Inside this service’s implementation, the startCommand()
override calls checkPasswordBeforeSwitch()
that processes the intent and then calls SpaceManager.switchUser()
from where the switch process is kicked-off.
The vulnerability lies in the way the password requirement is enforced inside checkPasswordBeforeSwitch()
, as the existence of a boolean extra is sufficient to skip the prompt. This means that one can bypass password entry when sending the service start intent with the params_check_password
extra set to False. This can be achieved using the ADB shell, without need for root access, by issuing the following command:
$ am start-service --ez params_check_password False --ei params_target_user_id 10 -a com.miui.xspace.TO_CHANGE_USER
The above command also works in reverse, i.e. switching from second to primary space by specifying the params_target_user_id
integer extra to 0.
Closer examination of the application’s AndroidManifest.xml
reveals the Service is not declared private
nor exported=false
. However, if not explicitly set, the Service is exported by default due to the existence of intent-filters, as seen in the following extract from the manifest:
<service android:name="com.miui.securityspace.service.SwitchUserService"
android:permission="android.permission.INTERACT_ACROSS_USERS"
android:process="com.miui.securitycore.remote">
<intent-filter>
<action android:name="com.miui.xspace.TO_CHANGE_USER"/>
</intent-filter>
</service>
Therefore, the security of the Service relies on the permission required to start it, as most applications holding the INTERACT_ACROSS_USERS
permission are system ones. This permission however is also held by the shell user, which is the access level a normal, non-root ADB shell provides.
Credit
The issue was discovered by Leonidas Tsaousis (@laripping) of F-Secure Consulting.
Timeline
Date | Summary |
---|---|
25/02/2020 | Issue reported to Xiaomi through HackerOne |
26/02/2020 | Bug triaged and bounty was rewarded. |
04/05/2020 | Contacted Xiaomi via HackerOne, requesting status update |
06/05/2020 | Xiaomi replied stating the issue has been fixed and would be tested in development version released by the end of the week |
09/05/2020 | Xiaomi states that the issue is fixed in development version 5.09 |
28/05/2020 | F-Secure release advisory |