Activity exported=false listed in activity chooser - android

I have two similar applications (one free, one paid).
An activity is defined with exported="false"
<activity
android:name=".MyActivity"
android:exported="false"
android:noHistory="true" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.mine" />
</intent-filter>
</activity>
When I call startActivity with the appropriate implicit intent from the free app, the activity picker appears.
I don't understand why the activity from the paid app appears, since it is exported="false"
I suppose I can add an intent filter based on the URL, but my question is: why does the activity from the other app appear when the doc reads
Whether or not the activity can be launched by components of other applications

I don't understand why the activity from the paid app appears, since it is exported="false"
Because you have a matching <intent-filter>. Since you do not need the <intent-filter> for a non-exported activity, simply delete it and use an explicit Intent when starting this activity.
why does the activity from the other app appear when the doc reads...
I had the same question and was told that this was expected behavior and the bug is in our app for having a useless <intent-filter>. Quoting Dianne Hackborn:
I would generally consider this a bug in the app -- if you have an activity that you aren't allowing other apps to launch, why the heck are you publishing an intent filter that they will match to try to launch? The security of the activity (whether it is not exported or requires a permission) is not part of intent matching. ...this scenario (publishing an activity that matches intents other applications will use but then restricting it to not be launchable by other applications) is not useful if not outright broken.

Related

Android Vulnerability Exported activity=true

I have an application that has only 1 activity "MainActivity" and it must be divided in fragments, because there are 3 windows, one of them is the user details, and this activity (the main activity) has exported=true.
I want to know if this entails a security flaw in an Android APK:
I log in the application
I start the activity with drozer: run app.activity.start --component com.member com.member.MainActivity
I can see the user details, but not in the first display, I need to press another tab, which must be another fragment inside the MainActivity.
Is it the normal behavior?
It is true that exported activities can be used by apps with a different uid, but the user must be logged in, which problem does it entail?
Regards!
Is it the normal behavior?
If by "the normal behavior" you mean that exported activities can be started by third-party apps, then yes.
It is true that exported activities can be used by apps with a different uid
If by "used" you mean "started", then yes.
For example, this activity of yours probably has this <intent-filter>:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
This says "hey, anything that is a launcher, please include me in your roster of launchable activities!". The launcher is how most Android device owners start apps. If your activity is not exported, then the launcher would not be able to start your activity, and as a result the user will not be able to use your app.
Note that having an <intent-filter> on an <activity> automatically sets android:exported to true — you do not need to declare this manually.

SingleTask activity, but opened through two different applications

This image was quite helpful for understanding the
functionality offered by the launhmode singleTask, taken from here
however, I understood this in case of the same application, I am having issues understanding
what if both tasks belong to two different Applications
Confusing Scenario(fictional),
I was going through an app and the app offered an action to send
emails, I selected 'send email' option.
My phone's default 'email app' will be picked and its activity (which is
declared as singletask) will be opened.
While I was typing my email content, I switched to some chat app and
the app gets crashed and offered me an option to report an issue
over email to the developer, Now when I will select 'Report' , my email
app(which is the same default email app ) will be opened.
Now as the Email app's root activity is singletask, will my content
which I wrote will be visible to me?
The main thing is this time, the tasks/stacks belong to two different apps.
Even though you are using 2 different applications, it will work in the expected way:
if your singleTask activity already exists, that copy will be used, with the method onNewIntent() being called
if it does not exist, it will be launched as per normal
More technically, reproducing the definition from your link:
The system creates a new task and instantiates the activity at the
root of the new task. However, if an instance of the activity already
exists in a separate task, the system routes the intent to the
existing instance through a call to its onNewIntent() method, rather
than creating a new instance. Only one instance of the activity can
exist at a time.
This can easily be verified by making an activity a target for sharing text and singleTask in the manifest:
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Now add some logging to the onCreate() and onNewIntent() methods and do some scenario testing.
Something I found particularly useful when testing the various launchmodes is the following ADB command:
adb dumpsys activity activities
This outputs a lot of text (it may help to reboot the phone before doing this - adb reboot) showing details of the activity task stacks. This can be used to show you that your singleTask activity "rehomes" itself as it gets launched via different applications.
As for the question about the emails, I think that will depend on which email client you are using, but I would hope that they handle the onNewIntent() method correctly, and save the current draft before displaying your new email.

POC - Start Service on boot without an Activity - Android 4+

This question may seem a trivial but I've been struggling with it.
I'm trying to start a service on boot and everything works fine if I start it at least once from the mainActivity (launch activity), something like:
AndroidManifest.xml
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<activity
android:name="com.example.mainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.example.bootReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service android:name="com.example.someService" android:enabled="true" android:exported="false"/>
...
bootReceiver.java
...
startService(new Intent(getApplicationContext(), com.example.someService.class));
...
mainActivity.java
...
startService(new Intent(getApplicationContext(), com.example.someService.class));
...
With the above code I'm able to run the service after every boot without any problems.
As a POC, I'm trying to start a service without any activity, or at least without the mainActivity, just by declaring the service on the AndroidManifest.xml or by creating new activity (invisible?) that is launched at the same time as the default launcher activity.
As far a I know, this isn't possible on android 3+ (4+?) due to security reasons.
Is there any way to achieve this ?
Can I start 2 activities from the AndroiManifest.xml when the user launches the app?
I'm sorry if my question isn't 100% clear, I've tried to explain it the best I could, if you cannot understand it, please leave a comment bellow. Tks.
As far a I know, this isn't possible on android 3+ (4+?) due to security reasons.
Android 3.1, actually, to help prevent drive-by malware.
Is there any way to achieve this ?
Something has to use an explicit Intent to invoke some form of IPC on one of your components, to move the app out of the so-called "stopped state" that is preventing you from receiving the broadcast. So, something needs to either:
start one of your activities via an explicit Intent, or
start one of your services via an explicit Intent, or
send a broadcast to one of your receivers via an explicit Intent
(I don't know if trying to connect to a ContentProvider will work, though arguably it should)
The key is the explicit Intent. That's why invoking an activity from a home screen launcher works, because the Intent used to start your activity will be an explicit one.
However, in the absence of such an activity, you would need to find something else that would use an explicit Intent to invoke one of your components. Certain specialized services (e.g., an input method) probably get invoked with an explicit Intent if and when the user activates that app's capability via the system Settings app. If you're a plugin for some other app, that other app might use an explicit Intent to work with one of your components. You can ask the user to install the Android SDK, learn how to use the command line, and invoke an adb shell am command to start one of your components. And that's about all I can think of off the top of my head. None are exactly general purpose solutions.
or by creating new activity (invisible?) that is launched at the same time as the default launcher activity
I have no idea what you think that would achieve. If the user starts up your launcher activity, you're already out of the stopped state and will receive broadcasts as normal.

App protection with LVL and explicit intents?

I've an app using the LVL. It consists (for simplicity) of two activities: The first one called LVLActivity checks the licence. If it fails, it simply finnishes, otherwise it launches the second activity called MainActivity with an explicit intent.
In the manifest, there is
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".LVLActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".MainActivity">
</activity>
</application>
Is it possible for someone else to write a small app that launches the MainActivity with an explicit intent?
Is this kind of setup is enough for a reasonable protection?
I believe MainActivity can be started from another app via:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.package", "com.package.MainActivity"));
startActivity(intent);
So, no, this would not protect your MainActivity per se, but you could have some kind of required shared data between LVLActivity and MainActivity, so that MainActivity would stop if this data is not existing.
But, be advised, that even this would not stop users who could reverse engineer code. To guard against this you should not have any sensitive data inside your application on devices - this basically means you should perform all business logic on server and only send data that is safe for given user back to the device. Of course you need to have some kind of user authentication+authorization on the server.
Why don't you do the license check in your main activity? It's the way Google recommend.
Aside from that, you can perform a license check whenever you want, but #Peter Knego is correct in saying that if someone really wants to get around the license check, then they will do so.

Android Can Applicaton Detect How it is being Launched?

Is there a way for Android application to detect how it is being launched? whether by a BOOT or by user launching the application from the application list?
When my application is launched on boot I don't want any activity to show at all. When the user specifically launches it from the application list, then and only then would I want the main activity to show. If I could detect whether the launch was a user launch or system boot launch I might be able to control this.
What you're looking for is the Intent that started the application. In the manifest file of your Android project you can specify which Intents will launch which Activities. The documentation page for Intent actually has a really thorough explanation of how to use this feature, with example code and everything:
http://developer.android.com/reference/android/content/Intent.html
The Intent that will be called when a user selects your application from a launcher will look like:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
If you want a different Activity to launch when the phone boots (there's an intent filter value "android.intent.action.BOOT_COMPLETED"), you just add a different IntentFilter to the Activity's tag in the manifest.

Categories

Resources