Series of vulnerabilities in system_server and mediaserver

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.

cveold

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