前言
前文系统的总结了组件会有什么安全问题,本文详细的从不同的组件切入,深入的解析组件的实现方式。组件安全https://blog.csdn.net/xiru9972/article/details/123537641?ops_request_misc=&request_id=7a89a72fdd464cee90c20b2b88549c11&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~koosearch~default-1-123537641-null-null.268%5Ev1%5Econtrol&utm_term=%E7%BB%84%E4%BB%B6&spm=1018.2226.3001.4450
相关知识
1. 生命周期
"Activity"是指在Android应用程序中执行的一个单独的用户界面组件,它通常是一个屏幕,用户可以与之交互。Activity有一个生命周期,其中包括多个不同的状态和回调方法。以下是Activity的生命周期:
- onCreate():当Activity第一次创建时,此方法被调用。在此方法中,可以进行初始化,例如设置布局文件,绑定视图元素等。
- onStart():当Activity变为用户可见时,此方法被调用。在此方法中,可以开始执行一些动画或其他用户体验效果。
- onResume():当Activity进入前台并开始与用户交互时,此方法被调用。在此方法中,可以启动一些后台任务,例如启动服务或注册广播接收器。
- onPause():当Activity失去前台焦点,但仍然可见时,此方法被调用。在此方法中,可以停止所有的动画或其他用户体验效果,以节省系统资源。
- onStop():当Activity被完全遮盖或者不再可见时,此方法被调用。在此方法中,可以停止所有后台任务,例如停止服务或注销广播接收器。
- onRestart():当用户返回到Activity时,此方法被调用。在此方法中,可以重新初始化一些数据或者重新绑定一些视图元素。
- onDestroy():当Activity被销毁时,此方法被调用。在此方法中,可以释放所有资源,例如取消注册广播接收器或释放绑定的服务。
2. 启动方式
分为显式启动和隐式启动
- 显式启动:显式启动是通过指定要启动的Activity的类名来启动Activity的方式。例如:
Intent intent = new Intent(this, MyActivity.class);
startActivity(intent);
在这种情况下,启动的Activity是明确指定的,因此称为显式启动。
- 隐式启动:隐式启动是通过指定一组Intent过滤器来启动Activity的方式。Intent过滤器是在Activity的清单文件中定义的,用于描述Activity可以响应哪些Intent。在隐式启动中,Intent不指定要启动的Activity的类名,而是指定Intent的一些属性(例如Action、Category、Data等),然后系统会查找与这些属性匹配的Activity来启动。例如:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.example.com"));
startActivity(intent);
在这种情况下,Intent指定了Action为ACTION_VIEW,Data为"http://www.example.com",系统会查找响应这种类型Intent的Activity来启动。
3. Intent Filter
Intent过滤器(Intent Filter)用于描述一个组件(例如Activity、Service、Broadcast Receiver)可以响应哪些Intent。Intent过滤器包含一组Intent属性,例如Action、Category、Data等,用于描述组件可以处理的Intent类型。
在组件的清单文件中,可以使用<intent-filter>元素来定义Intent过滤器。例如,以下是一个Activity的清单文件示例,其中定义了一个响应ACTION_VIEW Action和http和https数据类型的Intent过滤器:
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
</activity>
在这个例子中,MyActivity可以响应ACTION_VIEW Action和http和https数据类型的Intent。当用户点击一个http或https链接时,系统会查找可以处理这种类型Intent的Activity,并启动MyActivity。
4. 加载模式-Launch mode
Activity 有四种加载模式:
- Standard(标准模式):默认的加载模式。每次启动Activity都会创建一个新的实例,无论该Activity是否已经存在。如果Activity已经存在,则该Activity会被放置在任务栈的顶部。
- SingleTop(单顶模式):如果要启动的Activity已经在任务栈的顶部,则不会创建新的实例,而是直接使用已经存在的Activity。如果Activity不在栈顶,则会创建一个新的实例,并将其放置在栈顶。
- SingleTask(单任务模式):启动该Activity时,系统会检查任务栈中是否已经存在该Activity的实例。如果已经存在,则会将该Activity及其之上的所有Activity全部出栈,并将该Activity移动到栈顶。如果不存在,则会创建一个新的实例,并将其放置在栈顶。
- SingleInstance(单实例模式):该模式下,系统会为该Activity创建一个新的任务栈,并且该任务栈只会包含该Activity的实例。如果要启动该Activity,则会将该任务栈调至前台,并将该Activity置于栈顶。
AndroidManifest.xml配置方式
activity android:name=".MainActivity" android:launchMode="singleTop"/>
5. 任务栈
在Android系统中,任务栈(Task Stack)是一种用于存储应用程序中活动(Activity)的栈结构。任务栈可以用来管理应用程序中的Activity,包括它们的启动顺序、顺序调整和恢复状态等。每个应用程序都有自己的任务栈,其中包含所有由该应用程序启动的Activity。
当一个Activity被启动时,它会被放置在任务栈的顶部。当用户按下返回键时,该Activity会被出栈,同时上一个Activity会被恢复并显示在任务栈的顶部。如果用户按下Home键或者切换到其他应用程序,该应用程序的任务栈会保留在后台,等待用户再次回到该应用程序。
任务栈的实现方式是先进先出(FIFO),即最先进入任务栈的Activity会被放在栈底,最后进入的Activity会被放在栈顶。如果某个Activity的启动模式为SingleTask或SingleInstance,它将会被放在任务栈的顶部并形成一个新的任务栈。
关于任务栈的一些配置也可以再AndroidManifest.xml中进行配置。
- android:launchMode:用于指定Activity的启动模式,包括Standard、SingleTop、SingleTask和SingleInstance四种模式。这些启动模式可以影响Activity在任务栈中的位置和行为。
- android:taskAffinity:用于指定Activity所属的任务栈的名称。默认情况下,所有Activity都属于应用程序的默认任务栈。如果Activity的taskAffinity属性与默认值不同,则该Activity将会被放置在指定的任务栈中。
- android:allowTaskReparenting:用于指定是否允许Activity在重新启动时从一个任务栈移动到另一个任务栈。如果该属性设置为true,则系统可以在需要时将Activity从一个任务栈移动到另一个任务栈,以便实现更好的用户体验。
- android:clearTaskOnLaunch:用于指定在启动该Activity时是否清除任务栈中的所有Activity。如果该属性设置为true,则启动该Activity时会清除任务栈中的所有Activity,并将该Activity放置在栈底。
- android:finishOnTaskLaunch:用于指定在启动该Activity时是否关闭任务栈中的所有Activity。如果该属性设置为true,则启动该Activity时会关闭任务栈中的所有Activity,并将该Activity放置在栈顶。
6. 可导出
这也是之前提到的组件安全比较重要的一点,如果组件的属性是可导出的,那么其风险性是比较高的。
具体来说,Activity的导出性依赖于以下两个因素:
- AndroidManifest.xml文件中的android:exported属性。该属性决定了Activity是否可以被其他应用程序启动。如果该属性设置为true,表示Activity可以被其他应用程序启动;如果该属性设置为false,表示Activity只能被同一应用程序内的其他组件启动。默认情况下,android:exported属性的值为true。
- IntentFilter的配置。IntentFilter可以指定Activity可以响应哪些Intent。如果IntentFilter没有指定任何Intent,则该Activity不能被其他应用程序启动。如果IntentFilter指定了某些Intent,则只有匹配的Intent才能启动该Activity。同时,IntentFilter还可以指定Intent的URI的scheme、authority、path等信息,以进一步限制Activity的启动
7. 常见方法
在Activity中,常见的方法包括:
- onCreate():当Activity第一次创建时调用,用于进行一些初始化操作,如设置布局、初始化界面控件等。
- onStart():当Activity由不可见状态变为可见状态时调用,用于准备界面数据。
- onResume():当Activity进入前台时调用,用于启动一些动画效果、注册广播接收器等操作。
- onPause():当Activity失去焦点时调用,用于暂停一些不必要的操作,如动画效果、注册广播接收器等。
- onStop():当Activity完全不可见时调用,用于释放一些资源、停止一些服务等操作
- onRestart():当Activity从停止状态重新启动时调用,用于恢复界面数据和状态。
- onDestroy():当Activity被销毁时调用,用于释放一些资源、取消注册广播接收器等操作。
- startActivityForResult():启动另一个Activity,并等待返回结果。
- setResult():设置Activity的返回结果。
- finish():结束当前Activity。
- getIntent():获取启动当前Activity的Intent。
- getWindow():获取当前Activity的窗口对象。
- setContentView():设置Activity的布局。
- onCreateOptionsMenu()和onOptionsItemSelected():创建和响应菜单项。
- setTitle()和getSupportActionBar().setTitle():设置Activity的标题。
Activity相关安全问题
Activity在Android应用程序中扮演着重要的角色,但如果不正确地使用它,可能会导致一些安全问题。下面是一些常见的Activity安全问题及其举例:
- 拒绝服务攻击:攻击者可以利用Activity的launchMode属性,让Activity在任务栈中重复创建,占用系统资源,从而导致系统崩溃或无法正常工作。
- 逻辑绕过攻击:攻击者可以通过Intent传递特定的参数,欺骗Activity执行意外的操作,从而绕过应用程序的逻辑检查,造成安全漏洞。
- 例如,一个需要登录才能访问的Activity,如果没有正确检查登录状态,就可以被攻击者绕过登录验证,直接访问敏感数据或操作。
- 再例如某二次密码验证可以通过直接打开可导出组件绕过。
- 任意组件执行攻击:攻击者可以通过Intent传递特定的参数,让Activity执行意外的操作,如启动其他应用程序、调用系统服务等,从而造成安全漏洞。例如,一个需要用户授权才能执行的操作,如果没有正确检查Intent的来源和参数,就可以被攻击者利用Intent欺骗执行,从而执行未授权的操作:
- 例如LaunchAnywhere
- 意图劫持攻击:攻击者可以通过恶意软件或社工手段让用户点击链接或下载应用程序,从而欺骗用户启动恶意Activity,执行非法操作,如窃取用户信息、发送短信等。
- 通常需要阅读Activity接受了intent之后做了一些什么事情,然后构造特定的POC进行攻击
后话
本文详细介绍了activity相关知识以及可能存在的安全问题,具体的antivity造成的问题可能要结合具体的场景进行进一步分析了。