Android Shared Storage protection issue - android

I had implemented Google Native Ads as given in Native Ads
It is working perfect in all devices except Android 4.x version. The crash log in console is
Non-fatal Exception: java.lang.IllegalArgumentException: Optimized data directory /storage/emulated/0/Android/data/com.myapp/cache is not owned by the current user. Shared storage cannot protect your application from code injection attacks.
at dalvik.system.DexFile.(DexFile.java:100)
at dalvik.system.DexFile.loadDex + 149(DexFile.java:149)
at dalvik.system.DexPathList.loadDexFile + 251(DexPathList.java:251)
at dalvik.system.DexPathList.makeDexElements + 219(DexPathList.java:219)
at dalvik.system.DexPathList.(DexPathList.java:96)
at dalvik.system.BaseDexClassLoader.(BaseDexClassLoader.java:56)
at dalvik.system.DexClassLoader.(DexClassLoader.java:57)
at ir.b + 31(ir.java:31)
at ir.a + 5(ir.java:5)
at iu.a + 1(iu.java:1)
at com.google.android.gms.ads.internal.ag.run + 5(ag.java:5)
at java.util.concurrent.ThreadPoolExecutor.runWorker + 1080(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run + 573(ThreadPoolExecutor.java:573)
at java.lang.Thread.run + 856(Thread.java:856)
From Above crash it shows as Optimized data directory /storage/emulated/0/Android/data/com.myapp/cache is not owned by the current user. Shared storage cannot protect your application from code injection attacks
I had search related question Android DexClassLoader error, 'optimized data directory .. not owned by current user' but that is too old and not related to Admob. If I remove Native Ad related code then it is running else it crash and simply log above crash.
Please note my app was working good with same nativeAd code before 13th Aug 2019. after that its not working with NativeAd code.
Please help.

It seems some injection attacks happens in your application through the mobile ad contents
Injection attacks happens in the Android apps following cases
1) No or bypassable validation checks
2) File overwrite vulnerabilities, and
3) Code trigger points
The first condition includes the case when
(1) apps do not perform integrity or authenticity checks on downloaded DRU resources or
(2) attackers are able to bypass such validation checks. The second condition indicates the case when the injected payload can overwrite executables.
(3)The third condition is met when there exists a code trigger point where the overwritten files are loaded and executed in the app’s context.
Remote code injection attacks are successful when these three conditions are met.
The attackers Injected payloads are stored in a specified location in accordance with the app’s DRU implementations, usually in the app’s data directory (/data/data/PACKAGE_NAME) or in external storage (such as an SD card).
If the DRU that an attacker targets is the application code update, the injected code is replaced with the existing code resource (e.g.,  .dex,  .jar, or  .so) and then loaded and executed when the app triggers the update logic.
This is happens because of server side not in client side.
The mobile ad contains some File Overwrite Vulnerabilities
so that app crashed.
Solution:
Validate the ad content in server side .whether its satisfied google terms and conditions.
For more details refer Large-Scale Analysis of Remote Code Injection Attacks in Android Apps

Related

Statement List Generator and Tester rejects its own generated content

So, basically I'm at step 1 of implementing App Links, I stumbled upon this tool:
https://developers.google.com/digital-asset-links/tools/generator
I give it my domain name, my package name, and I copy paste my App package fingerprint from the play store console. it generate an assetlinks.json file for me, I put it as required at https://my-domain/.well-known/assetlinks.json I test downloads, it works, then I ask this tool to test it, it says
No app deep linking permission found for package_name at my_domain.
my logs indicate that GoogleAssociationService came and took the file (200 status response and the correct number of bytes).
So basically I put the good values, it generates it, and then fetch it and tells me it's wrong, what am I missing ? how can he not be happy with what he generated itself ?
When we came across this issue we have also investigated logs of our proxy and have seen that the "assetlinks.json" file had been successfully downloaded.
In our case, the problem was with Content-Type. In our case, it was the "application/octet-stream" type. According to the documentation, Content-Type should have the type "application/json". We have changed the content type and everything started working as expected.
Check the requirements using the link above and verify that all of them are met by crossing off all potential reasons one by one.
Update 2022-10-30: The provided link is not available anymore. I have used a cached version to fetch the information below:
You must publish your JSON verification file at the following
location:
https://domain.name/.well-known/assetlinks.json
Be sure of the following:
The assetlinks.json file is served with content-type application/json.
The assetlinks.json file must be accessible over an HTTPS connection,
regardless of whether your app's intent filters declare HTTPS as the
data scheme.
The assetlinks.json file must be accessible without any
redirects (no 301 or 302 redirects).
If your app links support
multiple host domains, then you must publish the assetlinks.json file
on each domain. See Supporting app linking for multiple hosts.
Do not
publish your app with dev/test URLs in the manifest file that may not
be accessible to the public (such as any that are accessible only with
a VPN). A work-around in such cases is to configure build variants to
generate a different manifest file for dev builds.

Exposed GCP API keys warning received eventhough i restricted the api key to android specific app

I received a warning for Exposed GCP API keys , event if i restricted my api key to android application giving the package name and SHA-1 signing-certificate fingerprint.
Do you know how to get rid of this warning?
I read the GCP best practices and they say it is ok to make the restrictions to android application giving the package name and SHA-1 signing-certificate fingerprint, but the warning is still there.
I am using the maps static api like this:
https://maps.googleapis.com/maps/api/staticmap?center=" + coordinates +"&zoom=13&markers=" + coordinates + "&size=" + width + "x" + height + "&sensor=false" + "&scale=" + scale+"&key="+apiKey;
Thank you!
Do you know how to get rid of this warning?
Probably its because you have the GCP API key hard-coded in your code.
How to hide the API key
Do you know how to get rid of this warning?
Sometime ago I wrote a blog post entitled How to Extract an API Key from a Mobile App by Static Binary Analysis, where I show several ways that developers use to store the API key in their mobile app, and how they can be extracted by reverse engineering the APK:
we will see how to grab that API key from your mobile app by reverse engineering the binary in an effective and quick way with an open source tool. Once we see how easy it can be done, we will realize that it is even achievable by non-developers.
For this article I created the repository android-hide-secrets, and I will use it to show you how to hide the API key, where we will make use of native C++ code to store the API key, by leveraging the JNI interface which uses NDK under the hood.
Adding the cpp folder to your app
Copy this folder to the main folder of your app, and you should end up with it atapp/src/main/cpp.
Now copy the file api_key.h.example to api_key.h. Afterwards edit the file and add the API key for GPC where it says "place-the-api-key-here".
NOTE: the file api_key.h will not be tracked by your repository, once its listed to be ignored by git in the app/src/main/cpp/.gitignore.
Configure Gradle
Open your app/build.gradle and add this code:
externalNativeBuild {
cmake {
cppFlags ""
}
}
Retrieve the API Key at Run-Time
In order to be able to get the GPC API during run-time, just add this code to your class:
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
and also this code:
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
Then when you need the API key just retrieve it like its done here:
renderApiKeyForView(R.id.jni_value, stringFromJNI());
While in this demo app I am just rendering the API key in a view, in a production app you would use stringFromJNI() to add the API key to the request header.
Conclusion
As I mentioned in the blog post, when an API key is hidden with this technique its not impossible to retrieve the API key with reverse engineering, but is pretty hard once guess work is necessary to associate the strings returned from parsing the binary.
I believe that after you apply this technique the warning for Exposed GCP API keys will go away. Please let me know how it went.
WARNING
While this technique gives you some level of protection against reverse engineering and will solve your warning issue, it will not deter an attacker from grabbing an API key hidden in your app by performing a MitM attack as I explain in this other blog post, entitled Steal that API Key with a Man in the Middle Attack:
So, in this article you will learn how to setup and run a MitM attack to intercept https traffic in a mobile device under your control, so that you can steal the API key. Finally, you will see at a high level how MitM attacks can be mitigated.

How to get list of downloaded apps (paid/free) by a user from Google Play?

I recently came across this app Purchase Apps, which is somehow able to retrieve apps I've paid for in google play after I signed in using my google account.
I'm trying to find out how it is being done as I want to build a similar app, but for the free apps which were downloaded.
However, I can't find which OAuth API Scope was used for retrieving that information, even after going through the entire list of APIs.
EDIT:
I'm putting a new bounty on this question, as suggested by a similar question I've asked about here, and because here and there I don't see a real answer about how to do it, and what can be done with it.
I'd like to refine the questions into multiple pieces:
What is the API that can be used to get information of purchased apps? Where can I read about it? Please show a full, working example of how to do it.
Can it do more ? Maybe perform search? Maybe show free apps that were installed? Maybe the time they were installed and uninstalled? And the categories of those apps?
Are there any special requirements for using this API ?
EDIT: I'm putting a max bounty on this, because no matter how much I've read and tried, I still failed to make a POC that can query the apps from the Play Store that the user has ever downloaded (name, package name, date installed and/or removed, icon URL, price...), including both paid and free apps.
If anyone finds a working sample, show how it's done, and also show how you've found about it (documentation or anything that has led you to the solution). I can't find it anywhere, and the current solutions here are too vague for me to start from.
Issue is resolved. The exploit has been closed.
We will be closing this bug due to being logged in a Preview version of Android. If the issue is still relevant and reproducible in the latest public release (Android Q), please capture a bugreport and log the bug in https://source.android.com/setup/contribute/report-bugs. If a reply is not received within the next 14 days, this issue will be closed. Thank you for your understanding.
Latest update:
This is a bug and Google will address it in the next update.
We've deferred this issue for consideration in a future release. Thank
you for your time to make Android better
This answer has turned into a conglomeration of ideas and been edited to include information from discussion in the comments.
The androidmarket api, would be a customised api written by the developer. It's not available to the public.
To address your concerns in the comments. The developer would have utilised the current apis available through Android Developer and Google to create a project that manages all of these.
As for accessing Full Account Access, I'm not sure exactly how these developers have achieved this.
I'd recommend using the AccountManager, which is part of android.accounts, has access to credentials and a method getUserData. The account manager has access to passwords and is capable of creating and deleting accounts. This, possibly used with Content Provider
See Udinic/SyncAdapter Authentication.
To reply to your comment:
This blog should help you to get started. Write your own Android Authenticator.
How these apps actually work, I cannot tell you. They may also have different implementations (unless they're a collaborative effort behind the scenes, they most certainly will be different).
One guess. Firstly use GoogleSignInAccount with com.google.android.gms.auth.api.signin.
There a definition for scope, to determine the extent of the permissions the app is granted.
Using requestScopes(), the
public static final String PROFILE
.../ It lets your web app access over-the-air Android app installs.
For example:
GoogleSignInOptions gso =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail().
.requestScopes(new Scope("https://www.googleapis.com/auth/contacts.readonly"))
.build();
If full access can be gained a list of all apps used by the account holder can be found and compared to what's on the device.
Package Manager will retrieve a list of all apps currently installed on the device.
PackageInfo provides the details about the app.
INSTALL_REASON_USER will also filter out apps that have been actively installed by the user.
You might want to look at com.google.firebase.appindexing and Log User Actions. Different actions can be tracked.
The users account history is found at https://myactivity.google.com/myactivity.
A helpful link is the OAuth 2.0 Playground.
This github repo node-google-play, using node, is current and will call Google Play APIs. As did the archive that was used as an "unofficial" api, android-market-api, to query the market place.
App 1
The app claims to use the following permissions:
Version 2.1.8 can access:
$ In-app purchases
Other
receive data from Internet
view network connections
full network access
use accounts on the device
prevent device from sleeping
read Google service configuration
Noteworthy, the app doesn't set any permissions when there was a basic, install. I was unable to use any of the features, as I have no paid apps. So for the initial search - there were no permissions needed, which would indicate the app didn't have access to my account.
I checked the permissions - there were none set. So the only thing required was to accept the pop up, as displayed in your question.
App 2
The other app you refer to that does the same thing is more upfront about what is being accessed.
My Paid Apps
SECURITY/PRIVACY NOTICE
The first time you run this app, it will ask for full permission to your Google account. This is unfortunately
the only way to access the required information. No personal
information is stored, no information about your apps is shared with
the developer of this app, nor shared with any third parties.
Everything is kept on your phone only.
I've gone into detail over these apps in this blog post, which was for a university capstone project (no monetary gain). I'm inclined to think this is an exploit in the API and not status by design by Google, as there are no API calls to fetch purchases of apps other than the developer's own app. I hypothesize it's a zero day exploit, in which case there's no legitimate way to access this information.
In case of one of these applications (My Paid Apps), after checking the network traffic it is pretty obvious that it does use the Store's Account page to retrieve the list of paid applications.
Now, the mechanism it uses is the same mechanism that Google Chrome currently, and Pokemon GO supposedly at a point in time used.
In a nutshell, steps to do so are as follow:
Login:
What the mentioned program do for the first step is to log the user in and get access to the user's access token. To do so, it uses the android.accounts.AccountManager.getAuthToken() method. (See more: AccountManager)
However, as for the token scope, oauth2:https://www.google.com/accounts/OAuthLogin is requested.
It might be important to note that based on the OAth2 documentation from Google, this scope is not valid; however, it seems like a valid scope for Google OAuth v1.
Converting the newly retrieved access token to a ubertoken:
Now, what actually ubertoken supposed to do, is unknown and there is no official documentation about it. However, it was seen in the wild to be used by chrome browser to login users.
This is done by requesting the https://accounts.google.com/OAuthLogin?source=ChromiumBrowser&issueuberauth=1 page.
Converting ubertoken to website session:
Later on, using the newly created ubertoken it is possible to get a website session using the https://accounts.google.com/MergeSession API endpoint. After this step, the application is essentially capable of loading all personal pages that you can open using your browser while logged in; except some special pages including Payment settings.
Retrieving the list of paid applications:
Requesting and parsing the https://play.google.com/store/account page.
Following is the application's traffic as captured by 'Packet Capture':
As it is clearly visible in the picture, the end result is identical to what I get when I normally open the store's account page on my PC with Chrome Desktop:
Side note:
It seems none of these endpoints are documented as they are primarily used by Google's own programs and should be considered internal. Therefore I strongly recommend not using them in any program or code that you expect to run for a long time or in a production environment.
Also, there is bad news here for you too, it seems that the Google Play's account page only lists paid applications or special free apps (more especially OEM apps). I will try to find some time and dig deeper into the other application.
Interesting articles:
Pokemon tokens
Exploiting Google Chrome's OAuth2 Tokens
If you have root access, You can access /data/data/com.android.vending/databases/library.db
OnePlus3T:/data/data/com.android.vending/databases
-rw-rw---- 1 u0_a2 u0_a2 229376 2018-12-26 18:01 library.db
This database has all information, which app you have downloaded, which apps you have purchased, and even in which app you have done IAP.
Check ownership table, It has all information.
ownership (account STRING, library_id STRING, backend INTEGER, doc_id STRING, doc_type INTEGER, offer_type INTEGER, document_hash INTEGER, subs_valid_until_time INTEGER, app_certificate_hash STRING, app_refund_pre_delivery_endtime_ms INTEGER, app_refund_post_delivery_window_ms INTEGER, subs_auto_renewing INTEGER, subs_initiation_time INTEGER, subs_trial_until_time INTEGER, inapp_purchase_data STRING, inapp_signature STRING, preordered INTEGER, owned_via_license INTEGER, shared_by_me INTEGER, sharer_gaia_id TEXT, shareability INTEGER, purchase_time INTEGER, PRIMARY KEY (account, library_id, backend, doc_id, doc_type, offer_type))
Dealing with unofficial Google APIs is incredibly complicated territory. It's going to be possible to get this to work, but that's all I'll say. Proceed at your own risk.
The first thing you're going to need to do is get a Google Play auth token. This can be done several ways, but here's how they do it in Purchased Apps:
public static String getAuthToken(Activity activity, String userEmail) {
AccountManager accountManager = AccountManager.get(activity);
Account userAccount = new Account(userEmail, "com.google");
Bundle options = new Bundle();
options.putBoolean("suppressProgressScreen", true);
String token;
try {
Bundle result = accountManager
.getAuthToken(userAccount, "androidmarket", options, activity, null, null)
.getResult();
token = result.getString("authtoken");
} catch (OperationCanceledException e) {
Log.d(TAG, "Login canceled by user");
return null;
} catch (IOException | AuthenticatorException e) {
Log.e(TAG, "Login failed", e);
return null;
}
return token;
}
A few things to note here:
The above code must be run asynchronously. I recommend RxJava, but an AsyncTask will work.
You must supply a email for the account you want to use. I'll leave the details up to you but this is fairly easy using AccountManager.
After you have an auth token, you can now access any Google Play Store endpoint. The main one used by Purchased Apps is https://android.clients.google.com/fdfe/purchaseHistory. Another one you might be interested in is https://android.clients.google.com/fdfe/details?doc=(package name) (from APKfetch code). Here's a page with some more and some analysis. If you make a request to these APIs, you'll need to supply several headers:
Authorization - "GoogleLogin auth=(your auth token)"
User-Agent - "Android-Finsky/6.4.12.C-all%20%5B0%5D%202744941 (api=3,versionCode=80641200,sdk=" + VERSION.SDK_INT + ",isWideScreen=0)";
X-DFE-Device-Id - your device's Google Services Framework ID, obtained from AdvertisingIdClient.
X-DFE-Client-Id - "am-android-google"
Accept-Language - The device's language code, eg "en".
Now, you need to parse the response. Here's where things get tricky. These APIs returns a message encoded as a Protobuf, so it's essentially just binary data unless you have a schema (which of course, only Google has). One way to go about this in theory is to decompile the Google Play Store app and reuse their generated protobuf models with a tool like JADX.
Unfortunately, I've tried this and it doesn't really work. Protobuf model classes are just too complex for a standard decompiler. What you can use is a tool called PBTK. You'll ideally want to run this on the Google Play Store 6.1.12 APK, since that's the last version before they started using ProGuard. Do note that this program has two errors in its script that need to be fixed before running it: changing 'extracto' to 'extractor' in gui.py and removing the assertion statement on line 500 of jar_extract.py.
Now, that should output all of the response classes as .proto files. Create a folder under src/main called proto and drag the entire generated 'com' directory to it. You can delete everything that's not under com/google/android/finsky/protos. Follow instructions online to setup Gradle with the Protobuf Lite plugin.
When you want to parse a response, you can use the ResponseWrapper class, since they all appear to be contained under that.
That's about as far as I can take you. There's a good chance I got some part of this wrong; JADX is your best friend here, because the best way to figure out what an app is doing is by looking at its code. Hope this helps and happy developing!
you can get the package name of all installed apps on device and then get the information of every installed package that you find in the device from google play without any need to get to user account. there is some third party or unofficial apis to get google play apps details as json by getting the app package name. for example: https://42matters.com/
then use the received information for every package to find free ones.
i have two resources for you to consider, but first, in a word, no. there is no api from GOOGLE to let you do what you want, as these metrics arent stored in the phone, they are on the google play store servors, and google has no OFFICIAL api for the play store. you can however glean some info from these two sites:
https://www.quora.com/Is-there-an-API-for-the-Google-Play-Storeenter link description here
https://android.stackexchange.com/questions/162146/how-to-see-all-the-apps-i-have-downloaded-from-google-play-store
and this is enough to see how to accomplish this.
first, a list of what apps have been downloaded by an account is only referencable by the account. and this can be done through the play store. since your app will be installed on that users phone, this dosnt matter... you're in.
second, you will need a 3rd party API built for the GOOGLE PLAY STORE, there are some out there, check the first link.
using the api of your choice, you will send a get request, to the play store, and in return you should receive in most cases a json object to deserialize.
deserialize the object, and you will have your list. which list you get will depend on the endpoint you use, but that should be explained by/in the API itself.
good luck!

AWS Android SDK connection timeouts and retries

I have been using the AWS android sdk(s) to deal with files on S3 inside my android application. There were some issues that were being faced by the users and few of these are related to connection timeouts. While setting up the AmazonS3client in my application, I have set the timeout and the retries using the following code:
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setMaxErrorRetry(4);
clientConfiguration.setConnectionTimeout(10000); // default is 10 secs
clientConfiguration.setSocketTimeout(15000); // default is 50 secs
Everywhere I read, it says that the maxErrorRetryonly does retries for failed retryable requests. Do the errors related to the connection timeout and socket connection timeout also come under this category? If not, what is the solution for this case? I have been searching for this for quite some time now but did not get any clear answer on this.
Also, I have been facing two specific exceptions which I get in my TransferListener callback. There are:
Unable to store object contents to disk: Read time out (14% of all the users who face any AWS exception face this exception)
Unable to store object contents to disk: timeout (17.4% of all the users who face any AWS exception face this exception)
The above two are the most painful for us. I have been assuming that these occur because of there is no more storage left on the user device. I have been using the application specific directory in the external storage to store the files and now thinking to move these to the cache so that the system handles the cleaning of files if there is no more space left on the device. Do you think this is a good solution assuming that the problem is running out of space on the user device.
What are the other possibilities because of which the above mentioned storage related exceptions can occur?
This error occurs at three places in the SDK, out of which two places are significant and applicable here.
(1) https://github.com/aws/aws-sdk-android/blob/0958a37b4757c41cac40597b973ff417e0b758c4/aws-android-sdk-s3/src/main/java/com/amazonaws/services/s3/internal/ServiceUtils.java#L284
(2) https://github.com/aws/aws-sdk-android/blob/3983fda8c2d8703399ac4e9bf6ec0464d000a5af/aws-android-sdk-s3/src/main/java/com/amazonaws/mobileconnectors/s3/transferutility/DownloadTask.java#L161
I suspect that it is in the (2) which is throwing the exception in your case. This can occur for multiple reasons and storage not available is just one of them.
(1) The S3 object does not exist or the S3 bucket/object does not have the required permissions. Please check on AWS S3 Console if you have the required permissions for your users to access content.
(2) There might be a network interruption during the download. Check if there is proper network throughout the transfer
Check AWS CloudWatch Logs to see if there are any failures in the logs.

App Indexing in android

I have implemented the app indexing in my application but its not working and showing below messages.
Deep link page : http://m.cardekho.com/carmodels/Hyundai/Hyundai_EON
Google could not get all the resources for this page:
https://graph.facebook.com/v2.0/244697749072142/activities?access_token=&format=json&sdk=android
https://graph.facebook.com/v2.0/244697749072142?format=json&sdk=android&fields=supports_attribution%2Csupports_implicit_sdk_logging%2Cgdpv4_nux_content%2Cgdpv4_nux_enabled
https://graph.facebook.com/v2.0/244697749072142?format=json&sdk=android&fields=supports_attribution%2Csupports_implicit_sdk_logging%2Cgdpv4_nux_content%2Cgdpv4_nux_enabled
https://track.appsflyer.com/api/v2.3/androidevent?buildnumber=1.15&app_id=com.girnarsoft.cardekho
The error message refers to resources which are either disallowed for crawling, or can't be accessed, but are deemed important for the page structure. In this case it's the former.
At https://graph.facebook.com/robots.txt it's currently showing:
User-agent: *
Disallow: /
To work around this, you would either convince Facebook to remove the disallow line so clients can access those resources, or you could modify the app so it relies less on the roboted (disallowed) resources.

Categories

Resources