type
status
date
slug
summary
tags
category
icon
password
 
 

一、漏洞APP分析

 

1. AndroidManifest.xml

清单中声明了四个组件。两个Activity,其中MainActivity导出。还有一个FlagReceiver,未导出。还有一个FileProvider,也是未导出。
notion image

2. MainActivity

MainActivityEasyDroid中的MainActivity 一样,先是获取intent的数据,然后经过校验后使用webView.loadUrl(data.toString())进行加载,而且设置了setJavaScriptEnabled(true) 这意味着启用了JavaScript 。除此之外设置了setWebViewClient ,并且通过shouldOverrideUrlLoading 拦截请求,在内部校验intent 并且可以进行跳转。因此这里存在攻击点,即可以绕过getAuthority校验加载恶意html,在html内部使用JavaScript 构造重定向请求,然后跳转到指定的非导出Activity
 

3. TestActivity

TestActivity onCreate 读取Intent中的url ,然后使用WebView渲染,并且设置setJavaScriptEnabled属性为true,同时添加了一个JavaScripte接口webView.addJavascriptInterface(this, "jsi"),这意味着可以在WebView渲染的网页中使用js调用Android类中的方法,但是前提必须要在可以使用js接口调用的方法前面加上@JavascriptInterface的声明,在该类中的Te3t即为可以使用js接口调用的方法。
 
Te3t 则创建了一条通知,并且在创建通知的过程中使用PendingIntent.getBroadcast(this, 0, new Intent(), 0)), 该PendingIntent将执行一个广播操作,类似于调用Context.sendBroadcast()方法。通过获取这个PendingIntent,您可以在任何时候以PendingIntent创建者APP的权限执行这个广播操作,而无需调用sendBroadcast()方法。
方法原型public staticPendingIntent getBroadcast (Context context,int requestCode,Intent intent,int flags)
 
 

5. PendingIntent

 
Intent 是意图的意思。Android 中的Intent 正是取自这个意思,它是一个消息对象,通过它,Android 系统的四大组件能够方便的通信,并且保证解耦。Intent 可以说明某种意图,携带一种行为和相应的数据,发送到目标组件。
PendingIntent是对Intent封装,但它不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为。
💡
A组件 创建了一个 PendingIntent的对象然后传给 B组件,B 在执行这个 PendingIntent 的 send 时候,它里面的 Intent 会被发送出去,而接受到这个 Intent 的 C 组件会认为是 A 发的。B以A的权限和身份发送了这个Intent
上文提到的PendingIntent 则创建了一个广播PendingIntent ,这意味着其他APP获取到该PendingIntent 时可以以创建者APP的权限发送广播。
⚠️
PendingIntent 可变的,这意味着应用 B 可以按照 fillIn() 文档中所述的逻辑更新用于指定操作的内部 intent。换言之,恶意应用可能会修改未填充的 PendingIntent 字段,从而允许攻击者访问存在漏洞的应用中原本不支持导出的组件。
如果其他APP能够修改PendingIntent 封装的Intent 则可能会导致危险的事情发生,例如上文提到的广播,通过修改Intent然后发送广播可能会使被攻击APP未导出的广播接收器收到广播,受到攻击
如果您的应用以 Android 6(API 级别 23)或更高版本为目标平台,请指定可变性。例如,可以通过使用 FLAG_IMMUTABLE 来防止恶意应用填充未填充的字段:
在 Android 11(API 级别 30)及更高版本中,必须指定要将哪些字段设置为可变字段,以缓解此类意外漏洞。
getActivity()的意思其实是,获取一个PendingIntent对象,而且该对象日后激发时所做的事情是启动一个新activity。也就是说,当它异步激发时,会执行类似Context.startActivity()那样的动作。相应地,getBroadcast()getService()所获取的PendingIntent对象在激发时,会分别执行类似Context.sendBroadcast()Context.startService()这样的动作。
PendingIntent 是系统对于待处理数据的一个引用,称之为:token;当主程序被 Killed 时,token 还是会继续存在的,可以继续供其他进程使用。如果要取消 PendingIntent,需要调用PendingIntent 的 cancel 方法。

4. FlagReceiver

FlagReceiver 就是接收广播设置flag的接收器

二、攻击APP构造

 

1. 攻击方案

  • 第一步肯定是需要通过导出的MainActivity中的WebView设置不当的漏洞进入到未导出的TestActivity进行下一步攻击,这里面的绕过和攻击方案与EasyDroid题目中的思路一致,构造恶意html,通过@绕过域名检测,然后在html中添加重定向到Intent Scheme Url,使得webview在渲染时,被shouldOverrideUrlLoading拦截到后启动TestActivity
  • 然后TestActivity中的webview加载由Intent Scheme Url传入的url,导致下一个恶意html被渲染,该HTML通过js接口调用Te3t触发通知创建PendingIntent
    • 攻击者APP中创建MagicService服务,用于监听通知,在获取到被攻击APP发出的通知后就可以获取到被攻击APP创建的PendingIntent
    • 拿到PendingIntent 后即可重新填充Intent,使其的Action设置为com.bytectf.SET_FLAG并且添加flag参数将值设置为恶意html内容,然后使用send发送广播,当被攻击APP接收到广播后会设置flag从而将恶意html内容插入到flag中,污染flag文件
      • 当恶意代码被注入到flag中后在攻击者APP的数据目录创建软链接 symlink.html,指向被污染的flag,而第一步中的恶意html会再设置一个Intent跳转延迟执行,这个Intent与前者不同点就是S.url=file:///data/data/com.bytectf.pwnmediumdroid/files/symlink.html ,从而导致在TestActivity中再次通过WebView加载url时渲染symlink.html ,这导致被污染的flag文件被渲染,从而触发注入到flag中的恶意代码,将内容传送到远程
         

        2.攻击APP完整代码

        MainActivity.java
        MagicService.java
        AndroidManifest.xml

        3. 攻击结果

        notion image
         
         

        三、总结

         

        1. 考点

        notion image
         

        2.坑点

        ⚠️
        在构造evil3.html时第一步的S.url 中的http://:// 最好进行编码,否则在WebView渲染时会将其转为https:// ,从而导致访问出现问题,如果进行编码就不会进行转化。
        ⚠️
        被攻击APP中虽然有FileProvider,但是无法利用其进行攻击,按照官方的解释: sendBroadcast没法通过Intent的方式授予Uri权限,也就是会flags被忽略掉,类似的还有bindService。具体的原因没找到很好的解释,可阅读AOSP源码,关键函数checkGrantUriPermissionFromIntent
        ⚠️
        官方给出的环境是每次启动一个模拟器,接受一个APP,然后启动,如果还想进行攻击就需要重新连接再启动一个模拟器,并且每次在启动攻击APP后会使用adb设置允许监听通知adb shell cmd notification allow_listener com.bytectf.pwnmediumdroid/com.bytectf.pwnmediumdroid.MagicService
        ⚠️
        在MagicService中一定要加这两个方法,否则监听器只能监听一次,想重新测试必须重启模拟器,如果测试中途触发了crash,例如直接终止攻击者APP,可能是无感知的,但是表现在无法进行监听,重启即可解决。

        参考

        1. PendingIntent  |  Android Developers
        1. ‌⁢⁢⁡⁤⁤‬‌⁢⁤⁤⁡‍‍⁢‌‌⁣‌⁢‌‍⁡⁣⁤⁡⁤⁣‌⁢ByteCTF2021 writeup for Android challenges - 飞书云文档 (feishu.cn)
        1. (72条消息) PendingIntent重定向:一种针对安卓系统和流行App的通用提权方法——BlackHat EU 2021议题详解(上)_安卓app提权_安第斯智能云的博客-CSDN博客
        1. (72条消息) PendingIntent重定向:一种针对安卓系统和流行App的通用提权方法——BlackHat EU 2021议题详解 (下)_startanywhere 安卓_安第斯智能云的博客-CSDN博客
        1. (72条消息) Android基础——PendingIntent理解_者文的博客-CSDN博客
        1. 关于 PendingIntent 您需要知道的那些事 - 知乎 (zhihu.com)
        1. Android PendingIntent - 简书 (jianshu.com)
        1. 安卓Bug 17356824 BroadcastAnywhere漏洞分析 - 掘金 (juejin.cn)
        ByteCTF2021 ByteDroid1复现ByteCTF2021 EasyDroid复现
        • Twikoo