File verification

File verification ensures that files go where they should go - stop directory traversal attacks early with default deny, and explicit allow on every file

Verify files​

Imagine you have written code that looks like this:

if (intent.action == Intent.ACTION_SEND) {    
    val uri = intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as Uri 
    sendData(contentResolver.openInputStream(uri))
}

Your application in this case might be at risk of an attack that looks like this:

Intent(Intent.ACTION_SEND).apply {   
    putExtra(Intent.EXTRA_STREAM, 
        Uri.parse("file:///data/data/com.my.app/db/sensitive.db")
    ) 
}
    

In this example, we might allow an attacker to send sensitive keys, databases (etc).

Allow no private apps​

To prevent this type of attack, we can use the verify command in order to check a file (or a URI) before opening it.

val isFileSafeToOpen = uri.verifyFile(this) {}

By default, no files from your private directory is allowed - which is what you want in most cases.

Allow specific private file​

We can allow a specific file

val isFileSafeToOpen = uri.verifyFile(this) {    
    // This
    File(context.filesDir + "files/", "safe_to_read.txt").allowExactFile()    
    // Is the same as this:   
    addAllowedExactFile(File(context.filesDir + "files/", "safe_to_read.txt"))
}

Allow all files in a directory​

Instead of this, we can add a directory and allow all files in that directory

val isFileSafeToOpen = uri.verifyFile(this) {    
    // This    
    addAllowedParentDirectory(context.filesDir.allowDirectory())    
    // Is the same as this:
    FileUriMatcherBuilder.FileUriMatcherCheck(context.filesDir, false )
}

Allow all files and subdirectories​

At the moment /data/data/com.safe.to.run/files/abc.txt would be allowed, but /data/data/com.safe.to.run/files/subdir/abc.txt would not. To allow subdirectories:

val isFileSafeToOpen = uri.verifyFile(this) {   
  // This
  addAllowedParentDirectory(context.filesDir.allowDirectoryAndSubdirectories())
  // Is the same as this:
  FileUriMatcherBuilder.FileUriMatcherCheck(context.filesDir, true)
}  

Allow any file​

We would not recommend doing this ⛔:

val isFileSafeToOpen = uri.verifyFile(this) { 
    allowAnyFile = true
}

Last updated