Android 6.0 permissions in defense and attack

03.07.2017

Every day in mobile devices reveal vulnerabilities that can be exploited by intruders. They can send SMS to a paid number, they can collect a large database of contacts and sell it, or they can compromise a particular person. Successful exploitation of a vulnerability usually involves a number of conditions. But you can go the other way too! Give the user the right application (toy with birds), which in the manifest will be recorded a list of interesting information on the device. In this article, we’ll look at ways to get and store important information from an Android device.

The architecture of the Android OS is built in such a way that it allows you to exchange different kinds of information between applications. An application working with maps needs a location, a dictaphone – access to a microphone. Thus, everything is clear and transparent.

We explicitly prescribe the required data or capabilities in the application manifest and get them when installing. Nobody deceives anyone, everything is voluntary. But the problem is that users are terribly illiterate in information technology. Few people think why this same dictaphone requires your location or access to SMS. The application openly declares its intentions in the manifesto, and it would be strange to expect from it another behavior.

Long before all known revelations I realized that a toy with angry birds on your device is a snitch, as it wants to read the device ID and data about calls among other things. The simple question “Do you need this data?” reveals the true intentions of its creators.

When installing the application, the user is put in the position “or allow everything that he wants, or you will remain without the program”. Only a few will go to the store to look for an application with similar functionality, but with fewer requests (there can be no analogues at all), so users quickly get in the habit of pressing “yes-yes-yes” to all questions. Agree, it’s easy to get used to when during many years of offline life users have developed a reflex to automatically sign multi-page contracts, according to the principle “well, still they sign, there’s probably nothing wrong with it, and there’s only one way out – either I sign here or do not get it of what he came for”.

After installation, the spyware application does not even need to be started, since it can have a mechanism for receiving broadcast messages (BroadcastReceiver), which, upon receiving a message from the system, will launch a collection service.

If we take away all the permissions from the application, the OS can simply give it empty values in order to avoid the fall of the program. You can fool the application by telling it knowingly false data (the location of the North Pole) or just zeros. For example, an application can ask for a list of contacts on the device, and the developer assumes in its architecture that it can be empty (a completely new device). There is nothing to suspect, and the data is saved, and the application has not broken down.

On such tricks had to go up to the version of Android 6.0 Marshmallow. In it, a new mechanism for working with permits appeared.

It allows you to give and take permissions while the application itself is running. For backward compatibility of old applications (that is, the value of targetSdkVersion is less than 23), the old mechanism for requesting installation permissions works. Updated applications must request permission in the process. In the settings of the application, we can see what the application has access to, and if desired, withdraw this access.

Consider the operation of this mechanism on a device with the version of Android 6.0.

Let’s install the birds, but before the first launch we will take away all their rights. When requesting rights when installing from Google Play, we see that the targetSdkVersion of the application is less than 23. The settings screen tells us about the somewhat overstated interests of the creators of the application.

How about a little to shorten them?

After revoking the permissions, I started the game, and it turned out that it did not prevent the normal work. Apparently, the background data collection service does not affect the main game interface.

Now let’s look at the work with the updated Skype application. Here we have a part of the manifesto of a “similar” application. The list of permissions and requirements from the application manifest inspires:

<uses-feature
  android:name="android.hardware.camera"
  android:required="false" />
<uses-feature
  android:name="android.hardware.camera.autofocus"
  android:required="false" />
<uses-feature
  android:name="android.hardware.telephony"
  android:required="false" />
<uses-feature
  android:name="android.hardware.microphone"
  android:required="false" />
<uses-feature
  android:name="android.hardware.bluetooth"
  android:required="false" />
<uses-feature
  android:name="android.hardware.wifi"
  android:required="false" />
<uses-feature
  android:name="android.hardware.location"
  android:required="false" />
<uses-feature
  android:name="android.hardware.location.network"
  android:required="false" />
<uses-feature
  android:name="android.hardware.location.gps"
  android:required="false" />

<permission
  android:name="com.skype.android.permission.READ_CONTACTS"
  android:permissionGroup="android.permission-group.PERSONAL_INFO"
  android:protectionLevel="normal" />
<permission
  android:name="com.skype.android.permission.WRITE_CONTACTS"
  android:protectionLevel="signature" />

<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />

<permission
  android:name="com.skype.raider.permission.C2D_MESSAGE"
  android:protectionLevel="signature" />

<uses-permission android:name="com.skype.raider.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<permission
  android:name="com.skype.raider.permission.RECEIVE_ADM_MESSAGE"
  android:protectionLevel="signature" />

<uses-permission android:name="com.skype.raider.permission.RECEIVE_ADM_MESSAGE" />
<uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" />
<uses-permission android:name="com.nokia.pushnotifications.permission.RECEIVE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

<permission
  android:name="com.skype.permission.ACCOUNT"
  android:protectionLevel="signature" />
<uses-permission android:name="com.skype.permission.ACCOUNT" />
<uses-feature
  android:glEsVersion="0x20000"
  android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT" />
<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" />
<uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT" />
<uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE" />

If only users saw this …

If we want to keep at least a small fraction of the private life, it remains to rely only on the operating system. Consider the process of installing the application. When installing from the market, no dialog boxes are displayed – all permissions the application will ask afterwards. Let’s check in the settings.

Run the application. Sequentially there are seven requests.

Consistently reject all requests, and Skype turns into an internet chat :).

Wait, did I say “online chat”? And why did not he ask for permission to access the Internet? And all because the permits are divided into two groups: ordinary and dangerous. Access must now only request the last. A list of normal resolutions can be found here. And there are dangerous permits (and their groups). To create permission requests, there are specific materials: templates for using permissions requests, recommendations for accessing permissions, and a full list of permissions.

With theory, we have sorted out more or less, now we turn to practice.

We get into the list of contacts (in a good way)

Enriched with this new knowledge, let’s write a small application in which we will read data about user contacts through requests in the interface and in the service. As it was recently revealed, some applications very often like to read this data (it is not surprising – suddenly there something has changed, and the creators of “good” applications do not know).

Click on the button, we check the OS version and, if it is 23 and higher, we make a request for rights:

public void setRequestReadContacts(View view) {
  // Check for already given permissions
  if (hasSelfPermission(this, Manifest.permission.READ_CONTACTS)) {
    // Permission is, we show contacts
    showContacts();
  } else {
    // Permission is not present, we send a request
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS);
    }
  }
}

 

After the dialog in the onRequestPermissionsResult method, you need to process the response:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
  if (requestCode == REQUEST_READ_CONTACTS) {
    if (verifyAllPermissions(grantResults)) {
    // Permission is, we show contacts
    showContacts();
    } else {
      Toast.makeText(this, "Permission REQUEST_READ_CONTACTS was not obtained", Toast.LENGTH_SHORT).show();
    }
  } else {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

Read the contacts in one line with the transitions to the new line:

private String readContacts() {
  Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
  String names = "";
  while (phones.moveToNext()) {
    names = names + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)) + "\n";
  }
  phones.close();
  return names;
}

We show contacts in the window, when you click on the window, it disappears:

public void createWindow(String contacts) {
  LayoutInflater layoutInflater
    = (LayoutInflater) getBaseContext()
    .getSystemService(LAYOUT_INFLATER_SERVICE);
  View popupView = layoutInflater.inflate(R.layout.popup_window, null);
  if (mPopupWindow != null)
    mPopupWindow.dismiss();
  mPopupWindow = new PopupWindow(
    popupView,
    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
  LinearLayout ll = (LinearLayout) popupView.findViewById(R.id.PopUp);
  TextView tv_message = (TextView) popupView.findViewById(R.id.tv_message);
  tv_message.setText(contacts);
  ll.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      mPopupWindow.dismiss();
    }
  });
  mPopupWindow.showAtLocation(mMainLayout, Gravity.CENTER, 0, (int) (mSidePopup * 0.3));
}

Here the result of reading contacts:

We get into the list of contacts (in a bad way)

Now we will do the same, but in the service, as it should be to a bad application. The service will not send any requests, but will try to just read the contacts in the forehead.

We will start the service on the event of connection to Wi-Fi.
Service code:

public class ReadContactsService extends Service {
  public ReadContactsService() {
  }

  @Override
  public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
  }

  private String readContacts() {
    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
    String names = "";
    while (phones.moveToNext()) {
      names = names + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)) + "\n";
    }
    phones.close();
    return names;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(getBaseContext(), readContacts(), Toast.LENGTH_SHORT).show();
    return START_STICKY;
  }
}

Receiver Code:

public class WifiReceiver extends BroadcastReceiver {
  public WifiReceiver() {
  }

  @Override
  public void onReceive(Context context, Intent intent) {
    NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    if (info != null && info.isConnected()) {
      // Doing our work
      Toast.makeText(context, "Connected", Toast.LENGTH_LONG).show();
      Intent myIntent=new Intent(context,ReadContactsService.class);
      context.startService(myIntent);
    }
  }
}

If the application has rights, the service will show Toast the message with the list of contacts, if it is not right, it will cause an error with the message. Now examine the behavior of the application if you set targetSdkVersion to it below 23.

By default, the application has been granted rights, and everything is working properly without any requests. After disabling rights in the application settings, the contact list began to come empty. We did not receive any mistakes, but also contacts. So, without our knowledge, applications will receive irrelevant information.

Conclusion

The new version of Android includes more reliable and flexible rights settings for applications. We can say that in the new version our data is protected more efficiently, but this does not mean that you can now blindly agree with all the proposals coming from the pop-up windows. Be watchful!

Нашли ошибку в тексте?

Leave a Reply

Your email address will not be published. Required fields are marked *