Android 15 访问 Android/Data 目录
自Android 14起,出现一个利用零宽度字符(
\u200b)绕过/sdcard/Android/data目录访问限制的漏洞。其原理是该字符在系统路径校验时被过滤,从而构造出合规的别名路径,使应用在未获授权时也能读取或写入该目录。该漏洞在Android 16上依然有效,已被MT管理器等应用采用。
博主博客
Android 6.0以前
应用只需要在 AndroidManifest.xml 下声明以下权限即可自动获取存储权限:
Android 6.0~10
需要动态申请权限:
// 检查是否有存储权限
boolean granted = context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED;
// 在activity中请求存储权限
requestPermissions(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
Android 10
暂停沙盒机制,在 AndroidManaifest.xml 加入:
<application
...
android:requestLegacyExternalStorage="true">
Android 11~12
使用官方提供的 SAF框架(Storage Access Framework)。
DocumentsContract.buildTreeDocumentUri(EXTERNAL_STORAGE_PROVIDER_AUTHORITY, String.format("primary:Android/data/%s", "com.uso6")
Android 13
使用 Shizuku 进行授权, 需要接入 Shizuku-API。
MT管理器使用了这种方式进行实现。
Android 14+
利用零宽度字符的 BUG 进行访问, 目前在 Android 16 依然生效。问题原因大概是,Linux 默认存储是大小写敏感的,而Android 是大小写不敏感的。为了这个特性,Android 启用了 Linux 内核中一个叫 case-fold 的特性,可以把大小写表示视为同一种路径。但是这个特性标准化时会忽略一些特殊字符,进而导致了这个问题。
MT管理器使用了这种方式进行实现。
File dataDir = new File(Environment.getExternalStorageDirectory(), "Android/data");
Log.e("nukix", "dataDir: read: " + dataDir.canRead() + ", write: " + dataDir.canWrite());
// dataDir: read: false, write: false
File dataDirZero = new File(Environment.getExternalStorageDirectory(), "Android/\u200bdata");
Log.e("nukix", "dataDirZero: read: " + dataDirZero.canRead() + ", write: " + dataDirZero.canWrite());
// dataDirZero: read: true, write: true
参考文献
Android 15 访问 Android/Data 目录
https://blog.uso6.com/archives/android-15-fang-wen-android-data-mu-lu
评论