Android App安全威胁分析及最佳实践

前言

我们的生活已经离不开App,且App承载了我们的金钱、私人信息、家庭视频监控、电子门锁、智能车钥匙等太多东西。
作为App的运营者必须将App安全性放在重要位置,否则因为安全漏洞导致用户信息泄露,不仅会造成用户流失、品牌受损,还会面临监管部门的巨额处罚。
App安全的重要性不言而喻。
作为研发人员,应该对App面临的安全威胁了然于胸,本文尝试归纳一下App面临的安全威胁。

常见安全威胁

不同用途的App,会面临不同的安全威胁,以下仅列举部分常见威胁
①用户数据被盗、被改
②窃听、偷拍、追踪
③敏感功能滥用:静默安装App、启动任意App私有组件等
④设备损坏:拒绝服务、手机无法开机等
等等,不一而足

攻击面分类

了解App的攻击面,堵住攻击路径,可有效的避免安全威胁

一、导出组件

App所出现的安全漏洞,其中接近80%是由于App的组件不该导出而导出,必须导出但没有进行白名单校验导致的
导出组件分为以下几种
①AndroidManifest.xml中的导出组件(Activity, Service, Broadcast Receiver, Provider)
②代码中动态注册的Broadcast Receiver和发送的广播
③系统App注册或实现的常驻Service(其他应用通过ServiceManager.getService(NAME)获取Binder进行调用,特征代码’.Stub’)

最佳实践

①所有组件尽可能设置不导出,即exported=false
②动态注册的Broadcast Receiver,默认使用LocalBroadcastManager注册
③避免发送implicit(未设置package或component)广播,且广播中去掉敏感数据
Android 9之后App接收implicit广播有限制
需配合Intent FLAG_RECEIVER_EXCLUDE_BACKGROUND和FLAG_RECEIVER_INCLUDE_BACKGROUND使用
④必须导出的组件,需要使用白名单限制可调用该组件的应用;白名单如果使用包名,则还需要校验App签名
Activity组件获取调用者身份

private String reflectGetReferrer() {
    try {
        Class activityClass = Class.forName("android.app.Activity");
        Field refererField = activityClass.getDeclaredField("mReferrer");
        refererField.setAccessible(true);
        String referrer = (String) refererField.get(MainActivity.this);
        return referrer;
    } catch (Exception e) {
        e.printStackTrace();
        return "No referrer";
    }
}

Service等组件获取调用者身份:使用Binder.getCallingUid()获取uid,然后通过uid获取包名及App签名信息
需注意:
If the current thread is not currently executing an incoming transaction, then its own PID is returned
通过Binder获取uid,在具体事务中才能获取真实的调用者身份,否则返回的Binder的uid(一般是1000)。即在onCreate、onBind等函数中获取不到真实身份
⑤使用自定义permission导出组件时,protectionLevel必须为signature或system
⑥FileProvider的resource配置,应避免设置root-path,所有path应配置详细的子目录

<paths>
    <external-files-path name="name1" path="Downloadxxx"/>
    <files-path name="name2" path="Downloadxxx"/>
    <cache-path name="name3" path="Downloadxxx"/>
</paths>

⑦组件(通常为导出组件)从外部获取的url、intent、filepath,应进行合理性校验,避免加载任意url、启动任意组件、沙盒文件泄露等安全威胁
校验url: url.host.endsWith(‘.domain.com’) 或 url.startsWith(‘https://www.domain.com/’)
从外部获取参数构造intent时,需要设定package、component、action白名单
对从外部获取的文件路径,应禁止file协议,仅允许content协议,并结合FileProvider防止访问沙盒任意目录

二、文件读写

SD卡目录(/sdcard/或/storage/emulated/0/)
在Android 11之前任意App可以读写
Android 11及以后/sdcard/Android/data/[pkgname]/目录为App私有目录,其他App非特权不能访问

沙盒目录(/data/user/0/[pkgname]/和/data/user_de/0/[pkgname]/)
除自身及同UID应用可以读写,另外root权限可以读写

与其他App共享uid(sharedUserId),其私有目录是共享读写权限的

最佳实践

①敏感数据不保存在SD卡目录
②特殊类型(apk, so, jar, dex, js, html)文件不保存SD卡目录
③敏感数据加密后存储沙盒目录,不能使用固定密码加密(可由账号信息派生出密码)
可使用androix.security库EncryptedFile
④对齐所有共享uid App的安全性
⑤沙盒文件禁止MODE_WORLD_READABLE or MODE_WORLD_WRITABLE

三、logcat日志

虽然恶意App无权限读取其他App的logcat日志,但在手机root情况下,将敏感数据、调试信息输出到日志仍然存在风险

最佳实践

①将logcat中的token、密码、密钥等信息用星号替换
②减少release版日志

四、与其他APP交互

App会以多种方式与其他App、系统进行交互。
大概有以下几类
①分享到Twitter、Facebook、微博、朋友圈,接收推送
②从系统选择图片、裁剪图片,选择文件等
③接收文件、图片分享

最佳实践

①启动社交App前校验签名信息,判断是否伪造(一般依赖SDK是否安全)
②及时、定期升级各类SDK
③用显式intent(限定系统App)从系统App选择图片、文件,且需判断返回的文件路径是否自身沙盒路径,防止沙盒读写权限泄露
攻击者App可以实现以下action,劫持图片选择功能
android.intent.action.PICK
com.android.camera.action.CROP
④从其他App、系统取得的文件路径,需判断是否自身沙盒路径,防止沙盒读写权限泄露
结合FileProvider的resource配置
⑤调用startActivityForResult和setResult函数前,按需清除intent中的危险flag
读、写文件权限
FLAG_GRANT_WRITE_URI_PERMISSION
FLAG_GRANT_READ_URI_PERMISSION
FLAG_GRANT_PERSISTABLE_URI_PERMISSION
FLAG_GRANT_PREFIX_URI_PERMISSION
⑥使用PendingIntent与其他App交互时,必需设定ComponentName,并设置FLAG_IMMUTABLE

五、网络交互

App会从服务器下载各种文件、数据,也可能会搭建网络服务提供数据
以下几种网络交互需注意安全风险
①从服务端下载zip,并解压
②从服务端下载apk/dex/so/js/html插件或App更新
③明文http传未加密敏感数据
④开启本地网络Socket Server监听(包括Unix domain socket)
⑤硬编码的服务端密钥

最佳实践

①使用https,且使用默认的TrustManager及HostnameVerifier
有为解决由于设备时间不一致而导致SSL校验出错,而使用自定义的TrustManager及HostnameVerifier,直接跳过校验
②使用https,且校验证书指纹(即SSL Pinning)
参考官方networkSecurityConfig属性配置
③使用https协议下载zip包,apk/dex/so等插件,保存在私有沙盒路径,防止其他App更改;使用前校验其完整性
zip解压时判断entry name中是否包含 …/ 特殊字符,防止跨域目录覆盖文件造成命令执行
④本地socket server需对接入端进行(密码)认证
⑤App使用的服务端密钥(比如firebase、云存储),禁止放在Apk源码中,应放在服务端使用

六、UGC内容

社区App,IM App,会有用户生产的文字、图像、视频内容,也可能成为攻击来源

最佳实践

①图片渲染库、视频渲染库优先使用Android默认库;若使用开源库,应及时升级新版
②App打开站外链接,应使用单独的webview加载,避免暴露JavascriptInterface
③接收图片、文件分享时,判断其路径是否为自身沙盒路径
android.intent.action.SEND

七、服务端API

App承载大部分业务,需要与服务端API交互,服务端的安全也需重点关注
服务端安全暂不展开

最佳实践

①注意注入、跨站脚本、上传、下载等参数类漏洞
②注意越权、频控、多步跳过、条件竞争等业务逻辑类漏洞
③可加上重打包检测(所有接口请求加上签名信息)

八、运行环境

检测运行环境是否存在root,App是否被调试,防止来自root权限的安全威胁

最佳实践

①对运行环境进行root检测、调试检测,并对用户进行风险提示
②对App进行安全加固
③重打包检测,结合服务端一起做

安全技术参考

①McAfee: secure-coding-android-applications https://www.mcafee.com/enterprise/en-us/assets/white-papers/wp-secure-coding-android-applications.pdf
②OWASP Mobile: mobile-security-testing-guide https://owasp.org/www-project-mobile-security-testing-guide/
③Android: https://developer.android.google.cn/reference/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值