CVE-2015-3854 ANDROID-20918350
CVE-2015-3855 ANDROID-20917238
CVE-2015-3856 ANDROID-20917373
Since those are posted prior to Android Security Bug Bounty Program launch, I’m posting to fulldisclosure for the record.
Details
A permission leakage exists in Android 5.x that enables a malicious application to acquire the system-level protected permission of DEVICE_POWER.
There exists a permission leakage in packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java, An attacker app without any permission can turn off battery save mode (which should be guarded by DEVICE_POWER permission, which is a system permission, lead to permission leakage), dismiss low battery notification.
Analysis
The PowerNotificationWarnings registered a dynamic receiver without permission guard, listening for the following actions:
- PNW.batterySettings
- PNW.startSaver
- PNW.stopSaver
- PNW.dismissedWarning
The PNW.stopSaver will call setSaverMode(false), thus call mPowerMan.setPowerSaveMode(false), which finally calls PowerManager.setPowerSaveMode(false).
(code of PowerNotificationWarnings.java) private final class Receiver extends BroadcastReceiver {
public void init() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
filter.addAction(ACTION_START_SAVER);
filter.addAction(ACTION_STOP_SAVER);
filter.addAction(ACTION_DISMISSED_WARNING);
mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, mHandler);
}
@Override public void onReceive(Context context, Intent intent) {
final String action = intent.getAction(); Slog.i(TAG, "Received " + action);
if (action.equals(ACTION_SHOW_BATTERY_SETTINGS)) {
dismissLowBatteryNotification(); mContext.startActivityAsUser(mOpenBatterySettings, UserHandle.CURRENT); }
else if (action.equals(ACTION_START_SAVER)) { dismissLowBatteryNotification(); showStartSaverConfirmation(); }
else if (action.equals(ACTION_STOP_SAVER)) { dismissSaverNotification();
dismissLowBatteryNotification();
setSaverMode(false);//PERMISSION LEAK HERE!
}
else if (action.equals(ACTION_DISMISSED_WARNING))
{ dismissLowBatteryWarning(); } }
An ordinary app cannot directly call this method because this API call is guarded by system permission DEVICE_POWER, however by sending a broadcast with action “PNW.stopSaver”, it can trigger this API call on behave of SystemUI, thus stops battery saver without user action and awareness.
Tested on Nexus 6/Nexus 7 (5.1.1)
POC code(do not require any permission)
Intent intent = new Intent();
intent.setAction("PNW.stopSaver");
sendBroadcast(intent);
Possible mitigations
Use a local broadcast mechanism, or use permission to guide the dynamic receiver.
Official fixes:
fixed in https://android.googlesource.com/platform/frameworks/base/+/05e0705177d2078fa9f940ce6df723312cfab976
Report timeline
- 2015.5.6 Initial report to security@android.com
- 2015.5.8 Android Security Team acks and assigned ANDROID-20918350
- 2015.6.1 The bug is fixed in Android internal branch
- 2015.7.24 CVE Requested, assigned CVE-2015-3854
- 2016.5.26 Public Disclosure