I have got lot of doubts to be cleared in the case of Android signature verification and its vulnerability.
Once we generate apk for an application we can unpack the apk and edit resource files using apktool. As we repack the edited apk back it loses its signature. I can resign the unsigned apk using the jarsigner with my own private key that i used while generating the apk. I found an application named zipsigner in playstore which can be used to sign such kind of unsigned apk.
So when this zipsigner signs the unsigned apk, whether the apk is signed with my same private key or with a different key? Because my META-INF folder still holds the XXX.SF and XXX.RSA files which holds the information of my private key. If it is with my same private key then the new apk will be an upgrade for my application or if it is a different key i will be having two different applications with same name.
From the above situations there are possibilities that malware could be included in my apk while repacking. There seems to be a loophole in Android's signature verification mechanism where the message digest of the files inside the META-INF folder are not included in the MANIFEST.MF as well as in the XXX.SF file. This creates a possibility for anyone to include malware codes inside these folders, repack the apk and resign it with the zipsigner application.
I was searching for a solution where i can prevent files being added into the META-INF folder and i found one from the below blog. But I'm unable to get the point of the solution. This looks like more of a research topic so there is not much information available in the internet. Can someone try and figure out the solution specified in the blog. The blog link is specified below the question.
http://blog.trustlook.com/2015/09/09/android-signature-verification-vulnerability-and-exploitation/
Private key is never part of a distributed APK, unless I misunderstood your question. Someone else signing on your behalf is not possible unless your own system is hacked.
The shared link (blog.trustlook.com) talks about Android skipping checking of files with .sf (and files with related extensions) extensions. So a malware could cloak itself in a file with one of these extensions. The fix mentioned there is an Android "system firmware" fix, not something that can be done at application level. This means, an OEM (Google itself, or Samsung/other) has to release an updated firmware to fix this. Check the latest updates, it might have been fixed already.
In my opinion, even if an user sideloads APK's, this is more of a nuisance than a real attack/threat. Refer to the Blackhat paper below for further details - https://www.blackhat.com/docs/ldn-15/materials/london-15-Xiao-What-Can-You-Do-To-An-APK-Without-Its-Private-Key-wp.pdf
You should also read this for potential ways of tamper proofing APK - https://www.airpair.com/android/posts/adding-tampering-detection-to-your-android-app
Reading from the other answers link black hat : APK issues
If you keep your private key safe, then only you can sign APKs, and only you will be able to publish them to a given store.
Extra information in the META-INF directory is not checked, and validated. This allows extra data to be added to the jar file, which could be used to smuggle information into the APK. But this would not be used by your APK file, and would not cause reputational damage.
There is a weakness in the testing algorithm, which means the validity of a certificate is not checked on the device if self-signed.
Data smuggling
Not checking the META-INF file is a side-effect of how the crypto- code works. In order to protect things you need to create a message which uniquely describes the message. This is a hash of the protected data. Unfortunately, the certificate, can't be included in this, as it is added after the hash is calculated.
So generally there are places which can be added to without breaking the signature. For windows and .exes, Microsoft's report here:MS13-98. In this case some installers used the unchecked data to choose where to download files from. This made them vulnerable.
Within an X509 certificate, there are unchecked fields. (unauthenticated attributes). Which makes any X509 based solution capable of smuggling data. Your protection, is the local copy you uploaded doesn't have the smuggled values.
If you don't rely on the un-authenticated data in the security directory, then you can't be made vulnerable to it being changed. So best option is to not do it.
Self - signing issue
Self-signing causes some checks to be missed. This allows an attacker to create an updatable package, which purports to be theirs. This is a copyright issue, rather than a security issue, as it is visibly the tampered binary (does not pass the self-signed check).
Is there any way of repacking the apk and signing the application with the same private key?
The private key is not available within the APK, so it can't be used to re-sign the data.
The files in the APK (outside META-INF) can not be modified without changing their hash.
whenever the apk is unpacked does it lose its signature information?
Un-packing the APK does not break its signature, and you can re-pack. You can remove items from the APK without breaking the signature. However, it is not possible to change resources, and code without breaking the signature.
Related
Is there a way to update my published app's first version if I have lost my signed apk, keystore and .pepk files? My laptop crashed - my data was not backed up. The only thing I have is that 1.aab file from Google play - I don't know how can it be helpful in my case.What can I do?
If it's published you can download the apk in the Google Play Console. APK extraction tools are there, as well as (dex2jar), what you'd have to do is rename file to zip, extract the contents, use dex2jar, change bundle ID/version or whatever in the manifest, resign it, then repackage the APK.
Those are the gist of it, high overview steps, you can easily find a detailed version on the internet or on SO if you look deeper.
You can use google console to recreate your signing stuff, keys, etc.
No, there is no chance to do that. You just learned how important a backup can be.
I have an apk file present in 2 standalone servers both of which have separate download links.
I would like to know if it is possible to detect from which link the apk was downloaded after the app was installed and opened.
The download is via browser and the one of the requirements is that the build has to remain the same.
If you are just installing your APK as a link directly on a file server, and the APKs are exactly the same, then no, there is no way to do this.
Here are some work-arounds:
Google Play provides a way for you to do this, but they are doing this through broadcasting an intent to the application after it has been successfully installed. You could release the APKs through Google Play privately through the beta / alpha channel, and take advantage of this feature perhaps. You'd not be able to use a private file server though.
You could create your own application that downloads and installs
the APKs and mimics Google Play's functionality which I described
above. This would probably be ridiculous for you to do, and I don't recommend it.
You could differentiate the APKs in some way. You could keep the content exactly the same, but configure some fields in the build logic through Gradle using the buildConfigField. You could also do split apks, use flavors, or a number of other different creative solutions if you wish.
So if for some reason the above suggestions don't meet your requirements, another solution that would be extremely hacky would be to use different APK file names. The browser would download the APK to the download folder, and you could probably look at the Android downloads folder after opening the app and look at the file name. This would not be reliable in any way though, as users could easily delete the file before actually opening your app, or there could be old downloads also. You'd have to look for base file names, and identify the most recent file based on creation date.
I have been looking at a few different tutorials, however am really struggling to see exactly how the Expansion Files can be firstly copied to a location that the user cannot access adn the how to use them in my actual app.
I will have a lot of key images within the Expansion file and therefore would also need to prevent users from playing the game until everything is downloaded.
Finally, I would have to also access a density based section for a lot of the images, along with a handful of raw files such as videos, this is what I currently have to work out which folder to open within the extension files.
String ExpansionFolder = "";
switch (getResources().getDisplayMetrics().densityDpi)
{
case DisplayMetrics.DENSITY_MEDIUM:
ExpansionFolder = "mdpi";
break;
case DisplayMetrics.DENSITY_HIGH:
ExpansionFolder = "hdpi";
break;
default: // This cover XHDPI, XXHDPI, TVDPI
ExpansionFolder = "xhdpi";
break;
}
Some sample code that i can use would be much appreciated.
I don't have sample code, because i haven't used expansion files myself, but specific answers to your questions do seem to be available at Android Developer APK Expansion Files page.
how the Expansion Files can be firstly copied to a location that the user cannot access adn the how to use them in my actual app.
from the "Storag Location" section of the Android developer page on expansion files (APK Expansion Files):
When Google Play downloads your expansion files to a device, it saves them to the system's shared storage location. To ensure proper behavior, you must not delete, move, or rename the expansion files. In the event that your application must perform the download from Google Play itself, you must save the files to the exact same location.
The specific location for your expansion files is:
[shared-storage]/Android/obb//
[shared-storage] is the path to the shared storage space, available from getExternalStorageDirectory().
[package-name] is your application's Java-style package name, available from getPackageName().
For each application, there are never more than two expansion files in this directory. One is the main expansion file and the other is the patch expansion file (if necessary). Previous versions are overwritten when you update your application with new expansion files.
If you must unpack the contents of your expansion files, do not delete the .obb expansion files afterwards and do not save the unpacked data in the same directory. You should save your unpacked files in the directory specified by getExternalFilesDir(). However, if possible, it's best if you use an expansion file format that allows you to read directly from the file instead of requiring you to unpack the data. For example, we've provided a library project called the APK Expansion Zip Library that reads your data directly from the ZIP file.
Note: Unlike APK files, any files saved on the shared storage can be read by the user and other applications.
From http://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String):
getExternalFilesDir
Returns the absolute path to the directory on the primary external filesystem (that is somewhere on Environment.getExternalStorageDirectory()) where the application can place persistent files it owns. These files are internal to the applications, and not typically visible to the user as media.
I will have a lot of key images within the Expansion file and therefore would also need to prevent users from playing the game until everything is downloaded.
From the "Downloading the Expansion Files" section of APK Expansion Files:
In most cases, Google Play downloads and saves your expansion files to the device at the same time it installs or updates the APK. This way, the expansion files are available when your application launches for the first time. However, in some cases your app must download the expansion files itself by requesting them from a URL provided to you in a response from Google Play's Application Licensing service.
The basic logic you need to download your expansion files is the following:
When your application starts, look for the expansion files on the shared storage location (in the Android/obb/[package-name]/ directory).
If the expansion files are there, you're all set and your application can continue.
If the expansion files are not there:
a. Perform a request using Google Play's Application Licensing to get your app's expansion file names, sizes, and URLs.
b. Use the URLs provided by Google Play to download the expansion files and save the expansion files. You must save the files to the shared storage location (Android/obb/[package-name]/) and use the exact file name provided by Google Play's response.
Note: The URL that Google Play provides for your expansion files is unique for every download and each one expires shortly after it is given to your application.
In addition to the LVL, you need a set of code that downloads the expansion files over an HTTP connection and saves them to the proper location on the device's shared storage. As you build this procedure into your application, there are several issues you should take into consideration:
The device might not have enough space for the expansion files, so you should check before beginning the download and warn the user if there's not enough space.
File downloads should occur in a background service in order to avoid blocking the user interaction and allow the user to leave your app while the download completes.
A variety of errors might occur during the request and download that you must gracefully handle.
Network connectivity can change during the download, so you should handle such changes and if interrupted, resume the download when possible.
While the download occurs in the background, you should provide a notification that indicates the download progress, notifies the user when it's done, and takes the user back to your application when selected.
To simplify this work for you, we've built the Downloader Library, which requests the expansion file URLs through the licensing service, downloads the expansion files, performs all of the tasks listed above, and even allows your activity to pause and resume the download. By adding the Downloader Library and a few code hooks to your application, almost all the work to download the expansion files is already coded for you. As such, in order to provide the best user experience with minimal effort on your behalf, we recommend you use the Downloader Library to download your expansion files. The information in the following sections explain how to integrate the library into your application.
You may also find Steps to create APK expansion file useful, if you haven't already seen it, though I don't know if Google has changed anything regarding expansion files since that question and its answers were posted.
I'm currently building an Eclipse plugin which creates and stores sensitive data, let's say "highscores".
As users can simply unpack the jar file, they are able to see the source code of the project. Thus they are able to cheat and create a faked highscore file by either changing the data in the file itself or writing to the highscore file (as they know how the data is encrypted from the source code).
Can I encrypt my jar file so that users cannot read the source code, but the plugin is still working properly?
As greg-449 already commented, that when the code is with user, it can be hacked in one way or the another. If Encryption of secure data is not going to help, you can move the secure data on your server.
Impact would be, it is available only when the user is online.
Another solution, a bit complex one:
Don't store High Score at all. Store/ log the user's activities to calculate high score. make the logs encrypted to add more security. Use salt, timestamp and secure key while encryption and a checksum to prevent manual changes to the file.
We are building a service to front fetching remote static files to our android app. The service will give a readout of the current md5 checksum of a file. The concept is that we retain the static file on the device until the checksum changes. When the file changes, the service will return a different checksum and this is the trigger for the device to download the file again.
I was thinking of just laying the downloaded files down in the file system with a .md5 file next to each one. When the code starts up, I'd go over all the files and make a map of file_name (known to be unique) to checksum. Then on requests for a file I'd check the remote service (whose response would only be checked every few minutes) and compare the result against that in the map.
The more I thought about this, the more I thought someone must have already done it. So before I put time into this I was wondering if there was a project out there doing this. I did some searching but could not find any.
Yes, it's built into HTTP. You can use conditional requests and cache files based on ETags, Last-Modified, etc. If you are looking for a library that implements your particular caching scheme, it's a bit unlikely that one exists. Write one and share it on GitHub :)