After analyzing my Android application with a security tool, it has detected a high level vulnerability "File unsafe delete check". I have investigated about this, and it seems that the problem is that the application uses "file.delete()".
That function is considered unsafe because data could theoretically be retrieved with a tool that scans all the storage device. So, if that way of deleting is "unsafe"... what is the "safe" way to delete files in Android? (to avoid getting that "security error" that is supposedly a "high level" one). What is the proper way to delete files in Android Development?
I am getting the same security warning in 2 different applications, one made with native Java and the other one with Xamarin Forms. Thank you very much!
what is the "safe" way to delete files in Android?
There is none for the vast majority of Android devices. You use delete() on File.
That function is considered unsafe because data could theoretically be retrieved with a tool that scans all the storage device
If the Android device happens to use a classic hard drive (spinning magnetic media), you can overwrite the data before deleting it. On any sort of flash media, that will be ineffective, as the physical location where the data is written can vary with each write operation ("wear leveling").
So, this really boils down to your objective:
If you feel that the user will be harmed if this data is available to be read, store it encrypted with a user-supplied passphrase.
If you are simply trying to avoid this warning, ask the developers of this "security tool" what they are expecting you to do. Or, find a better tool.
This is not an Android specific issue.
It has to do with how file systems work, and the physical storage media it self.
When you delete a file, regardless of API, what is actually deleted is the record in the files table.
The actual data on disk or flash storage remains.
There is a method for secure deletion:
Before deleting the file, overwrite its contents with garbage or zeros several times.
But, this method only works for magnetic media such as hard disks.
Android devices use NAND flash for storage.
Because the number of writes a NAND chip can take before it fails is a lot less than that of magnetic memory, these chips usually come with a mechanism that spreads out the write commands.
What this means is that even if you try to write random data or zeros over your file, there is no guarantee the actual data will be overwritten.
The writes may go to a different sector to avoid wear.
So, on one hand, for flash storage it is enough to overwrite the file once, but on the other hand, it is impossible to do correctly at application level.
If you want to make your application secure, you must make sure to store sensitive data encrypted.
Then, even if someone tries to read the raw storage, they wouldn't be able to recover the data.
Don't store user credentials (like passwords) in regular files on Android.
Use Android accounts API and let the OS manage security.
If you still need file storage but want to protect the data, encrypt it in memory and then write to file.
As said by the other answers the first thing to consider under a theoretical point of view is if there is really a need to store any sensitive information in files to be kept on customer side
If this is really the case, encryption is the real way to guarantee proper security. Files would be protected not only against the recovery after deletion but also during their known life on the device
That said, in the case of a vulnerability assessment - i.e. a static analysis of the code - it would not be immediate to detect that you are calling for a deletion [via file.delete()] of encrypted files. Or maybe you are just calling the deletion of files with nothing to hide
In both these cases the found vulnerability would just be a false positive. Which is part of the game because you can guess that it's quite complicated for an automated tool to understand if something really "deserves" protection or not
What you can do to get rid of the vulnerability is adding the logic to empty the files before calling file.delete(). You have a sample here for this purpose. This will solve the vulnerability detection you are experiencing
Related
I have an app that wants to have the ability to download files locally. A user can download a file (no restrictions to file type) and should be able to save it on the device so it can be used for other purposes. I would also like the user to be able to delete the file from the app (they would know which file is downloaded and which isn't, a ticker would indicate if it's backed up locally). Say it is a pdf file -- the user would want to open it with different apps or edit it if they have the ability to, or just share it via email. Considering we cannot opt out of scoped storage anymore (requirement to target 30), I got a couple of questions.
I've tried to use Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()) and also getExternalFilesDirPath(ctx, Environment.DIRECTORY_DOWNLOADS)). While the former is deprecated, it works for me in that the Files app can be used to navigate to the file in question (and possibly open/delete the file). On the other hand, I am not being able to delete this file from my app due to lack of permissions. Obviously, the latter path is unable to be navigated to by another app (or is it? I haven't found a way, hence the question).
The other thing I've considered using is the MediaStore API but I'm struggling to see how this is an improvement over the old ways in terms of function. Disregarding moving back to manual content resolver and cursor usage, how should arbitrary files be sorted? Should I manually sort by mime types and have different methods for saving for specific media types? It sounds exceptionally tedious and counter intuitive. If this is the way, so be it, I will implement it, but it does not sound like the way to go. On the positive side, it at least sounds like a solution due to the content resolver's CRUD abilities.
I'm working on a RN app that uses a 3rd party library for the download paths, which old/new versions, respectively, use different paths (rn fetch blob and rn fetch blob util). Additionally, MediaStore API doesn't have a RN implementation as of right now, so everything would have to be done from scratch, too.
What are my options? In the short term I'm considering disabling the erase feature from the app (at least for now). Anything I am missing and should consider? Thanks in advance.
I did some testing and, with an Android emulator, outputted a few pathways:
Internal Storage context.getFilesDir() has path /data/data/package_name/files
Private External Storage with context.getExternalFilesDir(null) has path /storage/emulated/0/Android/data/packagename/files/
Public External Storage with Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) has path /storage/emulated/0/Pictures/
In my app, I've defined an object that has a timestamp string and an array for images (more specifically, paths to those images), and this information is stored in a sqlite database.
But is this a bad idea? Because if someone wanted to move this app to another device, wouldn't the paths change? I'm a little confused as to how files can be moved around, how different devices impact this situation, etc. I am confused as to what the correct approach is for storing image references in the sqlite table. Do you store absolute paths like above? Or do you store a number representing whether the pic is internal/private external/public external and pull that way regardless of device/file structure?
I'm just trying to make sure I don't publish an app that lacks some critical feature simply because I misunderstood something. Like if I start using an app that can take pictures/store them internally, it's all on internal storage, all on this phone. But if I want to start saving pics to an SD card or something else, I have to change where I store the pics and how I reference them. And what if I upgrade my phone? I'd have to somehow carry/transfer all that stuff to a new infrastructure, etc. Or the "cloud", even.
In other words I am just trying to understand all the possible use cases, here, in terms of how Android app data is stored and transferred.
Your questions are a little broad. I will try to answer them in turns:
But is this a bad idea?
Not in itself. The issue here is how are you managing changes and the Android alterations that may occur in the future (as well as the versions you are currently supporting)
Because if someone wanted to move this app to another device, wouldn't the paths change?
Relative paths would never change. They were implemented (I am guessing around API 2~6) to ensure that hard disk management would not be necessary in apps. By getting the Enviroment.getExternalFilesDir(stuffs..) you would garantee a path to the same file, regardless of readl disk allocation.
how files can be moved around, how different devices impact this situation, etc.
Files from Desktops (PC, Mac, Linux, Ubuntu, etc) follow a contracted with Android devices, that simulate the same disk system. This way, a PC can save a file (png, mp3, custom, etc) in a "root folder" that becomes the same root for Enviroment.getExternalFilesDir(stuffs..) BUT data private to your application is never accessible (on non-rooted devices), to the outside system.
Do you store absolute paths like above?
You can. But I believe this goes against the system best-practices. Saving a relative path, then building a File object, in regards to that path is the correct approach. Do note that the File class in Android expects you to know a bit about the file you are refferencing.... either its extension, name regex, physical location, relational location, etc... you need to know at least one of those.
Finally, what I think you asked:
Can the user replicate the same content in different devices?
For this, you must ensure that the user is "know" for instance, using the Play Store account, you can then have a repository, and have devices syncronize with that repository. Or even add a "export" function, that copies files, and imports them somewhere else.
I am currently working on a (commercial) logistics project. We build a (partially) automated storage system in which the goods are stored randomly (think of nano-amazon). The positions of the objects are stored on the main computer and we are at the moment implementing the offsite backup via WAL (any objections?). One of our problems is that we have to operate during a power blackout and we can't produce enough energy for our computers for the worst case duration of the blackout which could be several hours. [This probably will never happen as we are in Germany, but there are some regulations we need to fulfill].
So my idea is to use a tablet [cheaper than a laptop], send the WAL-files to it so that the user can access the data during the blackout. But so far, I have seen no server implementation for tablets (either android or ios). Isn't there any or did I just not find it?
But maybe I'm also moving into the wrong direction. The Database is rather small (<50000 objects in the warehouse with each < 1kb) and the information we need during blackout is just one table (object_id -> position_in_warehouse) so that I even think about writing this information into a file and using git to copy the changes to the tablet. We also only need to know which objects have been removed during the blackout so that this information can easily be migrated back to the original db.
Or do you have other ideas?
Does your time have any value to you? Discard the Android + PostgreSQL option right now.
Keep it simple. You can get a cheap laptop for practically nothing, especially second hand. Since you clearly don't care about it actually working as a backup option, that seems like a no-brainer. You can run a streaming replica with WAL archiving for fallback.
For your real fallback option, you're on the right track with writing out the data you require to a flat file and syncing just that. Remember to actually test it - you should actually use it occasionally and make sure it works.
BTW, for your WAL-streaming backups, I suggest PgBarman, which will manage retention and rotation for you. You should also do logical dumps, and remember to test your backups.
I don't think there's a port of Postgres to Android - to use WAL files you'd need a working server. Even if it was ported, then you can't ship WAL files from x86 server to Android tablet - master and slave have to be the same major version, OS and architecture.
You really should just periodically export your data from Postgres to a simple file (I'd recommend SQLite) and just download it from a server. I suppose your tablets use WiFi and this file would be like 10MB zip-compressed.
Alternatively you could use rsync to keep this file updated. Don't use git - it will keep all previous versions of this file on your tablet - it would grow rather fast.
I will develop a mobile application on Android and iPhone/iPad that will contain a huge number of data (several MB, let's say 50 MB). Thus, these data will be stored on an external storage like a SD card.
Besides, they are critical and user must not be able to read them!!!
I guess how could I crypt/decrypt these data?
Here the main points to keep in mind:
Application is running on mobile device:
limited ressources (CPU, memory...)
These data will be read-only :
need only to develop the decrypt feature on the device
Application must quickly react:
response time to decrypt must be shortest as possible
Note: just a few amount of these data have to be decrypted according to the user actions:
For point number 3, I think to:
use an index mechanism to quickly find the data to decrypt.
use a C/C++ function to do the decryption on Android, using a Java/JNI bridge
Any other suggestions or methods from other experimented Android and iPhone/iPad developers ?
First of all, there's no way to store data on an external medium like an SD card on the iPhone.
This being said, what you like to achieve is impossible. If some encrypted data is meant to be decrypted on the device (even if only partially), this means the app needs to store the decryption key. This in itself is insecure, even with code obfuscation it is still technically possible for a motivated attacker to retrieve that key by reverse engineering your app.
So, if that data must not be made freely available through a malicious attack, don't store it in the device.
And even if you don't store it locally but instead transmit the decrypted data through a secure channel as needed - there's attacks for that, too.
It all boils down to this: There's always a vulnerability that may be exploited. You can try making it as hard for an attacker as possible to break in, but you must always keep in mind that it might be possible after all.
In Android applications, what is the best strategy to generate reports that can be viewed later by user? I'm talking about normal running of the application, not necessarily errors & exceptions.
I've a few options in mind but each one seems to have issues:
Logcat (use a specific tag “MyAppsLog”, provide user a functionality to read all statements logged using that tag)
Note: I believe the primary purpose of Logcat is for providing debugging info for the developer, not for the end user.
Manually open a flat file and append your logging statements to it.
Note: Can go this route if there is no standard mechanism for logging and report generation. Since this is such a standard requirement, I'm hoping not to re-invent the wheel. Also, if the application is re-installed the file can get lost. If written in sdcard/external storage to avoid this possibility, might not be private.
Use a third party tool like ACRA
or android-remote-stacktrace
Note: I think the purpose of these tools is crash-reporting, I don't think they are the best bet for standard report generation.
Many enterprise applications need to have a way to generate reports (normal running of app, not error), that the enterprise-user can view later. I'm hoping the answers here would be useful to more people than just me.
Well how about using an SQLite database, and dumping the log data in a table? Beats the flat file option I think. You can even aggregate dumped data or start queries on it.
Sqlite is heavy and taking lots of memory and process.
Advantages of flat file:
single point of all log info,
easy to manage,
easy to delete (clear cache)
performance (when file size grow up) performance of apps remain same
Anyone can read log file and can know which process is running on
if data is not big/complex, not that much important (if any one read it) then use flat file only.