大土豆安全笔记 | 讲讲广播保护机制失效漏洞

相比上一篇文章提到的研究,今天这个议题就显得比较专业了

《(Un)protected Broadcasts in Android 9 and 10》

  • https://www.blackhat.com/asia-21/briefings/schedule/index.html#unprotected-broadcasts-in-android–and–22378
  • http://i.blackhat.com/asia-21/Thursday-Handouts/as-21-Johnson-Unprotected-Broadcasts-In-Android-9-and-10.pdf
  • http://i.blackhat.com/asia-21/Thursday-Handouts/as-21-Johnson-Unprotected-Broadcasts-In-Android-9-and-10-wp.pdf

Android应用有四大组件,Activity,Service,Content Provider,Broadcast Receiver

定义一个广播接收器的方式如下,该广播接收器接收的Action为"android.intent.action.BOOT_COMPLETED",当系统内部在广播带有这个Action的广播,就会被这个广播接收器给捕获到

<receiver android:name=".NfcBootCompletedReceiver"> 
    <intent-filter> 
        <action android:name="android.intent.action.BOOT_COMPLETED"/> 
    </intent-filter> 
</receiver>

发送广播有两种方式:隐式发送和显式发送,前者只发送带有Action的广播,后者指定接收该广播的组件,当然Action也可以不指定,靠广播接收器内部判断也可以

Intent intent = new Intent("android.intent.action.BOOT_COMPLETED"); 
sendBroadcast(intent);

Intent intent = new Intent("android.intent.action.BOOT_COMPLETED"); 
intent.setClassName("com.android.nfc", "com.android.nfc.NfcBootCompletedReceiver");
sendBroadcast(intent);

要注意的是:这里举例的Action是系统启动时会广播的开机广播,属于被保护的广播,闲杂人等不能随便发送

<protected-broadcast android:name="android.intent.action.BOOT_COMPLETED"/>

有权限发送含有被保护的的广播判断规则如下,只有当前调用者的UID为ROOT_UIDSYSTEM_UIDPHONE_UIDBLUETOOTH_UIDNFC_UIDSE_UID或者callerApp.persistent标志位被设置为true

IMAGE

解释下callerApp.persistent标志位,它定义在AndroidManifest文件里,用于保证应用持续运行,只有系统应用的这个属性会生效,第三方应用利用这个属性保活是没有用的

<application
    android:persistent="true|false">

在Android系统里存在两百多个自带的应用,一般来说就存在/system/app/system/priv-app下面,记住它们都是系统应用即可

所有系统应用,都可以申请广播保护,如下在系统应用里定义广播即可受到保护,不被第三方应用随便发送

<protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE"/> 
<protected-broadcast android:name="android.intent.action.BOOT_COMPLETED"/> 
<protected-broadcast android:name="android.intent.action.LOCALE_CHANGED"/>

整个漏洞的核心就是这一张图,扫描/system/priv-app的时候,会添加SCAN_AS_SYSTEMSCAN_AS_PRIVILEGED两个标志位,而扫描/system/app的时候,只添加SCAN_AS_SYSTEM标签,在进行广播保护逻辑判断的时候,将没有SCAN_AS_PRIVILEGED标志位的系统应用内需要被保护的广播直接置为空

IMAGE

换句话来说,现在所有/system/app下的系统应用声明的保护广播,全都不被保护了,第三方也可以去发送这些被保护的广播

在Android 10里,作者搜索到了三个应用共十个被保护的广播

IMAGE

有想跟着分析的同学可以从这里下载对应的版本

  • https://dl.google.com/dl/android/aosp/flame-qq2a.200405.005-factory-e6617692.zip

额外插一句,Path Finder也可以批量扫这种,想不到写了个扫描引擎额外捡了很多功能

/home/wnagzihxa1n/UnpackROM/SystemApps/app/PresencePolling/PresencePolling.apk
==> <protected-broadcast android:name="android.provider.rcs.eab.EAB_NEW_CONTACT_INSERTED"/>
==> <protected-broadcast android:name="android.provider.rcs.eab.EAB_DATABASE_RESET"/>
==> <protected-broadcast android:name="com.android.service.ims.presence.capability_polling_retry"/>
==> <protected-broadcast android:name="com.android.service.ims.presence.periodical_capability_discovery"/>

不过奇怪的是我只扫描出了一个应用,手动查看了固件,也并不存在另外两个应用uceShimService.apkSSRestartDetector.apk,这个地方我需要再仔细想想原因

所以接下来以Slides描述为主

第一个漏洞是谷歌原生的应用,它最后可以操作联系人列表,我简单看了一下,这种攻击结果也没什么太大的意思

第二个漏洞来自小米,包名com.qualcomm.qti.perfdump,受保护的广播定义如下

<protected-broadcast android:name="android.perfdump.action.EXT_EXEC_SHELL"/>

广播接收器StaticReceiver会启动一个服务ExtRequestService,这个服务会从Intent里取出一个字段"shellCommand"作为命令行参数进行执行

public int onStartCommand(Intent intent, int flags, int startId) {
    ...

    String shellCommand = intent.getStringExtra("shellCommand");
    if(shellCommand != null) {
        String trimedShellCommand = shellCommand.trim();
        this.processShellRequest(this, trimedShellCommand);
        return 2;
    }
    
    ...
}

public void processShellRequest(Context context, String shellCommand) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Process shellProcess = Runtime.getRuntime().exec(new String[]{"sh", "-c", shellCommand});
            
            ...
        }
    }
}

第三个漏洞还是来自小米,包名com.qualcomm.qti.qmmi,不过这个漏洞没什么意思,只能泄露当前设备硬件信息,不多说了

手上刚好有个Samsung的固件,顺带扫描了一下,以下仅打印出部分被保护的广播

app/FilterProvider/FilterProvider.apk
==> <protected-broadcast android:name="com.samsung.android.provider.filterprovider.PACKAGE_ADDED"/>

app/MotionPanoramaViewer/MotionPanoramaViewer.apk
==> <protected-broadcast android:name="android.intent.action.MEDIA_MOUNTED"/>

app/SelfMotionPanoramaViewer/SelfMotionPanoramaViewer.apk
==> <protected-broadcast android:name="android.intent.action.MEDIA_MOUNTED"/>

app/MdecService/MdecService.apk
==> <protected-broadcast android:name="com.samsung.android.mdecservice.SMS_SENT"/>

app/DRParser/DRParser.apk
==> <protected-broadcast android:name="android.provider.Telephony.SECRET_CODE"/>

app/EmergencyModeService/EmergencyModeService.apk
==> <protected-broadcast android:name="com.samsung.intent.action.EMERGENCY_STATE_CHANGED"/>

修复方式是把漏洞代码挪个地方

  • https://android.googlesource.com/platform/frameworks/base/+/860fd4b6a2a4fe5d681bc07f2567fdc84f0d1580

漏洞代码会主动把没有SCAN_AS_PRIVILEGED标志位的应用声明的保护广播全部移除

private static void applyPolicy(PackageParser.Package pkg, final @ParseFlags int parseFlags,
        final @ScanFlags int scanFlags, PackageParser.Package platformPkg) {
    if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
        ...
        
    } else {
        ...
        
    }
    if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) {
        // clear protected broadcasts
        pkg.protectedBroadcasts = null;
        
        ...

修复后的代码将没有SCAN_AS_SYSTEM标志位的应用声明的保护广播全部移除,因为没有SCAN_AS_SYSTEM标志位就等于不是系统应用,那声明保护广播是没有意义的

private static void applyPolicy(PackageParser.Package pkg, final @ParseFlags int parseFlags,
        final @ScanFlags int scanFlags, PackageParser.Package platformPkg) {
    if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
        ...
        
    } else {
        // clear protected broadcasts
        pkg.protectedBroadcasts = null;
        
        ...
    }

像这种漏洞是先有分析的目标再去挖,还是说盯着一个组件去完整的看一遍,边看边思考可能的问题呢?

2020 MOBISEC的Slides和视频公开了,D类会议的东西也没什么好看的,我快速刷了一下大部分议题的Slides,确实没什么干货

  • https://mobisec.reyammer.io/slides

2021 ICSE这两天马上开始了,这是CCF推荐的软件工程领域的A类会议,热闹的很,Accepted Paper如下

  • https://conf.researchr.org/track/icse-2021/icse-2021-papers?#event-overview

我挑了几个有意思的,主要还是移动安全领域,今天先记一个

《Too Quiet in the Library: An Empirical Study of Security Updates in Android Apps’ Native Code》

  • https://arxiv.org/pdf/1911.09716.pdf

Android应用Native库文件的安全性一直都不是大规模挖掘的重点,自研的库一般不会开源,涉及到重要协议实现的模块甚至严重混淆,而且内嵌在应用之中,在没有文档的情况下不好进行测试,第三方库有的开源有的不开源,但接口文档都是齐全的,对于测试者来说是比较方便的

作者获取了Google Play平台排名前200的应用进行分析,共计7678个版本,其中包含66684个Native库文件,然后开发了一个LibRARIAN用于识别版本号,主要是基于导出函数,导入函数,导出全局变量,导入全局变量和库依赖关系,如果这些元数据算出来的相似性分数不好,则使用.rodata段的硬编码版本字符串,这个版本字符串可能不存在

第三方库的版本号识别其实是很困难的,不是所有升级都会放出来一个包告诉大伙我这个库修了什么什么问题,版本升级到了多少,之前我也想做来着,水平不够,耽搁了

剩下这几个我还没看

《Layout and Image Recognition Driving Cross-Platform Automated Mobile Testing》

  • https://arxiv.org/pdf/2008.05182.pdf

《RAICC: Revealing Atypical Inter-Component Communication in Android Apps》

  • https://arxiv.org/pdf/2012.09916.pdf
  • https://zenodo.org/record/4442663#.YKMsShQzb3a

《IMGDroid: Detecting Image Loading Defects in Android Applications》

  • https://o2lab.github.io/p/imgdroid.pdf

《A Context-based Automated Approach for Method Name Consistency Checking and Suggestion》

  • https://arxiv.org/pdf/2103.00269.pdf

《ATVHUNTER: Reliable Version Detection of Third-Party Libraries for Vulnerability Identification in Android Applications》

  • https://arxiv.org/pdf/2102.08172.pdf

《An Empirical Study on Deployment Faults of Deep Learning Based Mobile Applications》

  • https://chenzhenpeng18.github.io/papers/ICSE21.pdf

《App’s Auto-Login Function Security Testing via Android OS-Level Virtualization》

  • https://arxiv.org/pdf/2103.03511.pdf

《Fine with “1234”? An Analysis of SMS One-Time Password Randomness in Android Apps》

  • https://github.com/ooyyi6/pseudo-random-number-generation-test/blob/main/main.pdf

之前一个不存在的网站上面发了一段Android 12的系统动画,直接从六分半开始看

  • https://www.youtube.com/watch?v=GYRd8v2eRAA&ab_channel=FRONTPAGETECHFRONTPAGETECH%E5%B7%B2%E9%AA%8C%E8%AF%81

看完我只能说一个字:相当丝滑!

今年的开发者大会在北京时间五月十九号凌晨举办,也就是今天凌晨,正式公开了Android 12,国内已经可以下载Beta版本尝鲜了,正式版在秋天上线,到时候我看着买一台最新的Pixel,这丝滑的体验谁不爱啊

新系统对隐私做了比较多的改进,比如应用在使用摄像头的时候,会有一个小亮点提醒,这一点用MacBook的同学深有体会

Google Pixel 6的泄露图,挖孔全面屏

IMAGE

最近听说了一个朋友面试华为社招的经历

华为社招的流程是先面试,技术面,技术二面,中间可能有技术N面,最后一个是综合面试,部门老板亲自面,具体就是问问项目经历什么的,接着就是HR谈薪告知定级,前后大概耗时一个月,中间要提交毕业证,学位证,四六级证书,填写保密文件,职位申请,薪资证明,接着就是报上去业务部门审批,业务部门审批完报到人力资源那边进行Offer审批,Offer审批完之后,根据部门的坑位情况排队发放Offer

我这位朋友有一个技术面的面试官是华为21级的技术大佬,老惨了,问了整整一个小时的系统知识

接下来给各位讲点实在的,避避坑

面试前先问清楚到底有没有坑位,因为有的业务部门即使没有坑也会让你面试,然后拖着你,最后形成一个鱼塘,里面都是面试完但是没有完成审批的鱼儿,有新的鱼儿来,有老的鱼儿走,哪天有坑了就从鱼塘里捞一把提交审批

流程很长,非常长,不要裸辞,先拿到华为的Offer邮件,口头Offer没用,因为即使Offer审批完成也要根据部门坑位情况进行发放,可能你前面还有好几个已经完成Offer审批在等待坑位的

以上都是我这位朋友跟我分享的,不是官方,可能与真实情况有出入,而且不同部门政策情况不一样,希望我这朋友好运!

哦对了,他还没谈薪呢,听他说综合面试到现在满打满算已经一个月了