How do I restrict access to my ContentProvider to only my apps? - android

I want to export a ContentProvider for use by another one of MY apps. How do I prevent other apps from accessing it? If I use an android:permission attribute, can't 3rd party apps just apply that permission to their app? I really need to lock down access to my apps only.
Thanks in advance...

If I use an android:permission attribute, can't 3rd party apps just apply that permission to their app?
Well, you can use a signature-level custom permission (android:protectionLevel="signature"). Then, the app holding the permission and the app defending itself with the permission have to be signed by the same signing key.
There's a bug/limitation in Android that can allow an attacker, installed before your app, to hold this permission even though the attacker is not signed by your signing key. I go into that in more detail in this report (as it's a bit complex for an SO answer) and have a PermissionUtils class to help you detect that case.

Related

Android custom permission vs app signature

I have gone through the available documentation and SO posts on both these topics (custom permissions and app signature), my understanding is:
Apps signed with same key can use signature-level permissions
A custom permission should only be defined in one place and the app declaring the permission needs to be installed first
A custom permission can be defined in multiple apps if the apps share same signature
Now I need to define some components in one app that I will be using in another app signed with the same key, but according to this I don't need to define a custom permission and can place a signature check
If the functionality is only available to apps signed with the same signature as the providing app, you may be able to avoid defining custom permissions by using signature checks. When one of your apps makes a request of another of your apps, the second app can verify that both apps are signed with the same certificate before complying with the request.
I don't understand what is meant by signature checks, is there a way to place a check in manifest on that component or do I have to check it programmatically? If latter, isn't it better to define a custom permission in both apps instead (to negate installation order issue)?
is there a way to place a check in manifest on that component
No, sorry.
do I have to check it programmatically?
Yes. This pair of old projects demonstrate a bound service and a client that checks the signature of the service. Those projects are covered in a chapter in a chapter of this free old book. That sample has problems in modern Android, as an app can have multiple signatures. But, the SiganturesUtil class that it relies on shows how to get signatures from PackageManager for an installed app. You can then compare them with the expected value to determine if you are indeed talking to the app that you expect.
If latter, isn't it better to define a custom permission in both apps instead (to negate installation order issue)?
Signature checks are more flexible — they are not limited to two apps being signed by the same signing key. That, plus historical issues with custom permissions, may be why Google recommends signature checks over custom permissions on that page.

Acquire "signature" permissionlevel on Android

I'm building an Android app, and one of the permission I need is defined as:
android:protectionLevel="signature|system|development"
How do I get the signature protection level? Do I need to sign my application somehow?
Do I need to sign it with OEM ? (Samsung\HTC\LG)?
signature means that to be able to get access to the resource, your app have to be signed with the same certificate that the holder of the permission. If this is not your app you are trying to connect to, then you basically are out of luck. If that's system one then you are out of luck even more, This is documented here:
"signature"
A permission that the system grants only if the
requesting application is signed with the same certificate as the
application that declared the permission. If the certificates match,
the system automatically grants the permission without notifying the
user or asking for the user's explicit approval.
EDIT
Im trying to read logcat file through my application. this requires
the permission android.permission.READ_LOGS
You cannot access logs on stock ROM that are not created by your application. That's introduced for security reasons, so would not make sense to let you get it just because you need it. If you build own ROM, then you can have it, but then you should know this already.

Custom permission between two apps with different signatures

I have two application which are signed with different certs/keys.
I want to make authenticated call (to a service) from application A to app B (so no 3rd party can make such call).
Common solution for such things in Android is custom permissions with signature protection level. However, it won't work in my case, because two apps are signed with different certs (developed by different companies)
So, the question is. What is the best practice for this case, if I want allow only application A (or any apps developed by this company) to call/bind a service in app B?
There really isn't one, IMHO.
If the permission is not signature-based, the user can grant it to any app that asks for it, so a permission will not help you.
If you use services with the binding pattern, your Binder has getCallingUid(), which you can use to find the UID of the calling app. With some work, you can find out the package name for that UID from PackageManager. How you validate that package name is up to you (baked-in whitelist, try to make sense of the package's signature from PackageManager, whatever). That doesn't prevent somebody from messing with your APK and hacking your validation routine, though.

How to prevent other applications from define same permission name

My application define a permission with android:protectionLevel="signature".
<permission android:name="my.app.permission.EXAMPLE" android:protectionLevel="signature" />
My intention is make application modules that can be launched only by my signed app. These application modules have android:permission in its activities.
This works fine. but...
A third-party app can use the same permission name and changed the protection level to normal, like this
<permission android:name="my.app.permission.EXAMPLE" android:protectionLevel="normal" />
If my app is installed first, i can prevent others apps to override the permission. However, if one uninstalls my app and then installs his app it redefines the permission.
Is it possible prevent other application use the same permission name, for example, giving the permission a unique id like application package?
Although the Manifest is encrypted, anyone can read the permission name in log cat when it tries to start the activity that requires this permission (An exception is thrown having the required permission name).
There's no enforcement, only convention. Like the rest of the Java world, it loosely relies on domain name registration infrastructure. The idea is that you prefix your permission name with your public Internet domain name (e. g. com.myawesomecompany.myapp.MYPERMISSION) which you own.
Uniqueness of domain names is enforced by the registrar community, naturally.
Yes, the system is open for abuse.
EDIT: if you're securing a broadcast-based channel, you can add a two-way signature check if you feel like it. Call Context.sendBroadcast() with the permission name as a second parameter.
EDIT2: I feel you're overthinking this while closing your eyes at the bigger Android app security picture. Which is not impressive. Abusing the privilege infrastructure is not how one hacks into an Android app. If I set out to intercept your intents, I won't be putting together a fake intent receiver (activity, service). Instead, I'd connect with a debugger to the genuine receiver in your app, signature and all.
With publicly available tools, it takes minutes to put togther an Eclipse project for a given APK. Load it up into Eclipse, connect to a running process, set breakpoints in relevant system APIs (Android is open source, remember), voila. With a bit of extra effort, you can get decompiled Java sources for an APK and debug in terms of YOUR methods, as opposed to system ones.
copyed from Google Andorid Doc:
Note: The system does not allow multiple packages to declare a permission with the same name, unless all the packages are signed with the same certificate. If a package declares a permission, the system does not permit the user to install other packages with the same permission name, unless those packages are signed with the same certificate as the first package. To avoid naming collisions, we recommend using reverse-domain-style naming for custom permissions, for example com.example.myapp.ENGAGE_HYPERSPACE.
https://developer.android.com/guide/topics/permissions/defining
If you want to prevent other applications from changing your permission level, you can use system predefine permissions which have level "signature". No other regular app can define permission before system.
Use system permission to protect your resource doesn't mean your app have to sign with platform key.
example:
<service
android:name="xxx.xxx.xxx.exservice"
android:permission="android.permission.BROADCAST_PACKAGE_REMOVED" >
The only issue is AppStore would show which permission you use if below code shows in app's manifest.xml
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />
In this example, you can access you resource by the same sign key, but definitely you can't broadcast package remove.

Android apps able to communicate without permissions set

I was under the impressions that two apps were sandboxed and unable to call each other (by intents or contentresolver etc) unless the callee declared and enforced specific permissions and the caller used appropriate uses-permission elements? However, I have developed two apps, one containing a content provider, and another with activities that use the content provider. Neither have permissions declared enforced or used. I deploy them directly from Eclipse to my phone and they are able to use each other.
I have checked that they really are running as separate processes and user ids, and they are. Why am I not seeing security exceptions? Should Linux underneath, by default, stop this communication? They will be signed by the default DEBUG certificate. Does this give them more rights to "talk" to each other, i.e. if I signed with an explicit certificate would the sandboxing kick in?
As soon as I declare and enforce a permission in the content provider app the other app does need the uses-permission to allow communication.
Cheers
Yes, if your apps have the same signature, then they have access to each other. It's similar to package level permissions in java.
http://developer.android.com/guide/topics/security/security.html

Categories

Resources