Android ContentProvider安全注意

0x00 背景

一直没太搞懂ContentProvider,现在有点理解了,赶紧记下来。

0x01 AndroidManifest介绍

看这里可以发现ContentProvider可以设置这么多属性,下面说一下几个重要的。
https://developer.android.com/guide/topics/manifest/provider-element

  1. android:authorities
    一般就是你的包名加上ContentProvider的类名。

  2. android:enabled
    true的时候表示android系统可以实例化你的ContentProvider。我的理解是只有true的时候才能ContentProvider才能用,所以这个必须是true。(?)

  3. android:exported
    是否可以被外部调用。

  4. android:permission、android:readPermission、android:writePermission
    如果可以被外部调用的时候,外部App需要什么样的权限才能调用

  5. android:grantUriPermissions
    如果exported为false,或者外部App并没有可以调用本App的ContentProvider的权限时,但是我们可能仍然会想偶尔给外部App一次性的调用机会,则要把这个属性设置为true。典型的例子是比如邮件App里收到一个pdf附件,那么邮件App想让一个PDF App来打开自己的附件,但是必须限定只能打开这个附件,而不能赋予PDF App自己的其他文件的访问权限,这时就可以设置android:grantUriPermissions为true,并在自己的代码中进行如下的编程:

    //grant permision for app with package "packegeName", eg. before starting other app via intent
    context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    
    //revoke permisions after return from Intent
    context.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

参考:https://stackoverflow.com/a/18332000/2892850

0x02 path traversal的防范

如果ContentProvider里实现了openFileopenAssetFileopenTypedAssetFile这些接口的话,要注意防范path traversal,具体方法可以参见这两个链接:
https://support.google.com/faqs/answer/7496913
https://github.com/facebook/facebook-android-sdk/blob/5.x-branch/facebook-core/src/main/java/com/facebook/FacebookContentProvider.java#L147
在测试是否有path traversal的时候,可以使用如下命令:

adb shell content read --uri content://[authority]/../../../../../system/etc/hosts