AppWidget的风险分析与防护建议
2023-5-24 10:37:23 Author: mp.weixin.qq.com(查看原文) 阅读量:5 收藏

01
 AppWidget简介

Android官方的介绍:应用微件是可以嵌入其他应用(如主屏幕)并接收定期更新的微型应用视图。这些视图称为界面中的微件,您可以使用应用微件提供程序发布微件。能够容纳其他应用微件的应用组件称为应用微件托管应用。

微件是自定义主屏幕的一个重要方面。您可以将微件想象成“一目了然”的视图,它们让最重要的应用数据和功能一览无余,从用户的主屏幕即可进行访问。用户可以在其主屏幕面板间移动微件,如果系统支持,用户还可以调整微件的大小,按照他们的偏好量身定制微件中的信息量。

直观一点,就是桌面上的这些小部件:

AppWidget的几个部分:

  • AppWidgetProvider:这是一个BroadcastReceiver,它提供资源数据,由应用自己实现。

  • AppWidgetFramework:用于管理AppWidget,包括AppWidgetManager和AppWidgetService,属于系统服务。

  • AppWidgetHost:用于承载显示AppWidget,桌面一般会承担这个角色。

值得注意的广播:

AppWidgetProvider实际上是一个BroadcastReceiver,它特殊的地方在于,它不仅有onReceive()来接收广播,还有一些特定的方法接收特定的广播,这些特定的广播由AppWidgetService发出,以管理AppWidget的生命周期。

  • ACTIONAPPWIDGETUPDATE,对应onUpdate(),对应当需要更新AppWidget 时发送。

  • ACTIONAPPWIDGETDELETED,对应onDeleted(),当一个 AppWidget 实例被删除时发送。

  • ACTIONAPPWIDGETENABLED,对应onEnabled(),当第一次 AppWidget的实例被添加时发送。

  • ACTIONAPPWIDGETDISABLED,对应onDisabled(),在删除此AppWidgetProvider的最后一个 AppWidget 实例时发送。

  • ACTIONAPPWIDGETOPTIONS_CHANGED,对应onAppWidgetOptionsChanged(),当 AppWidget 的自定义附加功能发生变化时发送。

  • 任意广播(包括自定义广播和前面提到的特定的广播),对应onReceive(),每次接收广播都会在前面提到的每个方法之前调用它。

用户交互:

AppWidget的点击事件,由RemoteViews中设置的PendingIntent实现,调用setOnClickPendingIntent(@IdRes int viewId, PendingIntent pendingIntent)。用户点击后,便会触发PendingIntent中封装的Intent,去实现相应的功能。

02
 AppWidget更新的关键步骤

想要分析AppWidget的风险点,就需要分析AppWidget的生命周期,其中最重要的是AppWidget的更新。

AppWidget更新有多种情况,定期更新,响应用户交互,响应广播事件。

① 下图包含了三种情况,所以有三个起点:

  • AppWidgetService发送广播一般是定期更新,或者是管理其他的生命周期;

  • 用户主要是触发了事件,一般是点击了按钮,触发了PendingIntent;

  • 其他应用或者组件也可能会发广播给AppWidgetProvider。

② 在AppWidgetProvider收到广播后,发送AppWidgetId和RemoteViews给AppWidgetFramework,形成对应关系。

③ 然后AppWidgetFramework会通知AppWidgetHost需要更新,将AppWidgetId和RemoteViews发送给AppWidgetHost进行更新。

④ AppWidgetHostView只是一个容器,用来容纳AppWidget的View,通过RemoteViews获得真正的View,然后进行更新显示。

从流程上看,广播和PendingIntent是有风险的。

03
 风险点

3.1 接收任意三方发送的广播:

AppWIdgetProvider是一个BroadcastReceiver,它需要用广播来进行操控,有时候我们会用到自定义广播,如果它接收的广播能被任意三方发送,那么就能够控制该AppWidget,尤其是一些特权接口,可能会被恶意利用,AppWidgetService发送的广播都是Android原生广播,三方没有权限发送,我们更需要关注自定义广播。

3.2 不安全的PendingIntent被劫持:

不安全的PendingIntent能够被利用窃取应用的身份和权限来进行越权操作。虽然Android14中已经进行了限制,如果以Android14为目标平台的应用程序创建一个可变的PendingIntent,但未指定组件或包,系统将会抛出异常。

AppWidget利用PendingIntent来实现点击事件,在RemoteViews中设置,而RemoteViews是会被传递给AppWidgetHost的,如果该RemoteViews能被劫持,就能获得它的PendingIntent,导致安全风险出现。

现在问题就是如何能劫持到它的PendingIntent。

AppWidgetHost获得RemoteViews可以通过使用AppWidgetId向AppWidgetService查询。

目前只能由绑定该AppWidget的AppWidgetHost查询,在AppWidgetService中存在对请求者的校验:

所以目前只能自己建一个AppWidgetHost去添加AppWidget,然后获取它的RemoteViews。

获取到RemoteViews后,还要通过反射,来获取其中的PendingIntent,因为并未提供可以获得PendingIntent的公开API。

通过这样的次序逐层获得隐藏的成员变量mPendingIntent:

在添加AppWidget的两种方式中,AppWidgetPickActivity需要用户自己手动选择将要添加的AppWidget,直接绑定指定的AppWidget也会有添加AppWidget的授权弹窗,算是一种局限性,无法做到用户无感知。

04
 PendingIntent劫持演示

使用demo来实践一下:

AppWidgetProvider:com.example.appwidgettest

拉起目标:xxx.yyy.zzz

先写一个有问题的AppWidgetProvider:

然后写一个AppWidgetHost去绑定该AppWidget,

需要先申请权限,

在manifest中添加权限:

在运行时,用户必须显式向应用授予权限,以下代码可以拉起授权的对话框:

然后就可以进行绑定了:

绑定过后,我们就可以通过AppWidgetId去查询RemoteViews了:

PendingIntent就在RemoteViews中,RemoteViews就在返回的reply中,

从reply中获得PendingIntent,通过反射,逐次将PendingIntent剥离出来:

从此就能构造intent,以com.example.appwidgettest的身份去拉起xxx.yyy.zzz。

05
 如何规避风险

5.1 对广播做限制

对AppWidgetProvider设置权限保护,权限保护不能低于signature,不能让任意三方发送广播来控制AppWidget;

如果AppWidgetProvider不需要接收外部的广播,也可以将其设置为不可导出。

5.2 对PendingIntent做限制

如非必须允许PendingIntent接收者篡改信息,创建PendingIntent时一定要增加FLAG_IMMUTABLE为flag信息;

使用PendingIntent时,对于封装的Intent必须明确、显式的指定组件信息(以Android14为目标平台的应用已经强制要求可变的PendingIntent必须如此创建,否则会抛出异常);

建议在接受方有使用如data、action或extras内容进行流程控制时,主动使用默认内容占位;

非必要不建议设置FILL_IN相关flag。

参考文章:

[1] appwidget加载流程及其与app的通信:

https://www.jianshu.com/p/8ad60d0286ce

[2] 构建应用微件:

https://developer.android.com/guide/topics/appwidgets?hl=zh-cn

[3] Android中Launcher对于AppWidget处理的分析,AppWidgetHost角色:

https://blog.csdn.net/thl789/article/details/7893292

[4] Android AppWidget:https://juejin.cn/post/6979180597486829576

[5] Android源码:https://cs.android.com/

[6] 广播概览:https://developer.android.com/guide/components/broadcasts?hl=zh-cn#security-and-best-practices

[7] PendingIntent劫持问题分析:https://mp.weixin.qq.com/s/VxGDPzjssALOHv_sMIop8Q

[8] Android AppWidget系统框架:

https://blog.csdn.net/thl789/article/details/7879257

[9] PendingIntent重定向:一种针对安卓系统和流行App的通用提权方法——BlackHat EU 2021议题详解(上):https://mp.weixin.qq.com/s/lB3yV1-VE3X-CmqN2T5KCw

[10] Behavior changes: Apps targeting Android 14 or higher:https://developer.android.com/about/versions/14/behavior-changes-14#security

往期回顾

Android Provider安全问题深度解析

vivo X Fold2:全能且轻薄,隐私保护更周到!

magisk的原理与检测方法

如何防止你的隐私被泄露?这份指南告诉你

关注我们,了解更多安全内容!

文章来源: https://mp.weixin.qq.com/s?__biz=MzI0Njg4NzE3MQ==&mid=2247490934&idx=1&sn=a020c869ac605d532b2b59d36a59d153&chksm=e9b93b1adeceb20c8e39b3801a6de28a306950a12a5f72abfe3f99b1de2dde2c4eed0cfcb42c&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh