Does anyone knows what is the most secure way to store sensitive information in application? Because using internal storage and shared preferences is vulnerable if person who want that information have a rooted phone.
Case is that I have some kind of activation code which needs to be stored somewhere inside the phone (not on server) for further communication and authentication with server side, that code needs to be secured and not available to other apps and users, even on a rooted phone. Also, user can not be bothered with additional verification (he enters the PIN code when he enters the application and send that code to the server side for authentication) .
Bottom line, is there a secure way to store something and to be secure that it will remain hidden, even on a rooted phone?
Unfortunately the commenters are correct. There is no way to guarantee with 100% security that the activation code can't be hacked. Microsoft has spent millions of dollars on this, and there are still pirated copies of Windows out there, because at the end of the day you have no control of the code on the client. If you endow the client with the ability to decrypt or otherwise access this stored authentication code (without needing to go to the server), then someone can reverse engineer the app to undo your protection. This is true even if you retrieve a decrypt key from the server.
The best way to do this depends on your use case, but here are some ideas:
Have the client submit the "activation code" to the server, where you can blacklist it if you think it's stolen. This is how Windows works. This is the only option you have if you want to use an activation code and not bother the user.
Have the user register an account and have the app resubmit the user's credentials each time it runs. This way you have a user account to deactivate if you suspect piracy.
Have the server provide the decrypt key. This does not guarantee that the activation code stays safe, but it does up the bar for potential reverse engineers.
Drop the whole DRM idea completely, and focus your attention on making a good product. Studies that music companies have shown that dropping the DRM makes no difference in the number of people who buy your product.
Related
We have apps developed for both Android and iOS which interacts with devices via BLE and uses a Spring boot backend server in which they have registered and logged in. They can log in with the same account on either Android or iOS (obviously). During the interaction we can get codes that the user may need in the future. To handle that we currently do this:
Android: Encourage the user to write the code down. Use the users login information (username/password) to generate a symmetric key which is used to encrypt data which is then sent to and stored in our server. That way, only the user can retrieve it and decrypt it. Drawbacks would be the way we generate the key in itself and the obvious fact that a user that has forgotten password/changed password cannot decrypt the data anymore.
iOS: Encourage the user to write the code down. Then store it in KeyChain with the kSecAttrSynchronizable attribute so it can sync to iCloud KeyChain. That way the user should be able to get it on any other iOS device. Obvious drawback is that if the user chooses to switch to Android then the code cannot be retrieved there.
Is there anyway we can store sensitive user app data for both platforms? We could store it in our server but since we want the users to encrypt it themselves (so we can't see the content of the data) we need some unified way. There is no magic Spring boot feature to store "encrypted user data" for a specific user which only that user can retreive?
Have thought about using Google Drive and store it in the hidden app folder. But I'm guessing that wont work with an iOS app that uses the Google Drive SDK?
EDIT
Just to exemplify:
A user buys the device and connects it to its Android app. The user then changes the reset code of the device which is what would be needed if the device was ever "factory reset" (of course not factory, but cleared). When that is done we encourage the user to write this code down/remember it. Then lets say the the user loses the Android phone and buys an iPhone. He logs in to the exact same account but now might need to reset the device in order to start using it again. If that code could have been stored somehow using the account (or using the users google account or anything) then he wouldn't have to remember it.
I am thinking of creating a app that will contain personal user information for a memberships scheme, the basics, name, dob, a user ID and a valid from / expiry date.
I want to reduce the instance of hacking and having the data stolen. So I was thinking that I add the user information in the database, when the user logs in for the first time, the app connects to the data and downloads the users information to their phone and all personal data is removed from the database, the ID is used for the app to display valid from/expiry dates etc.
I am unfamiliar with iOS/Android app development. Can this work, do I store in a separate file and download to a user area in the app package or do I download a database to the phone, and what about when I need to update the app?
This is not good system design
In reality if a system is designed properly, with a security focussed mindset and deployed in a properly designed environment, this should not be a concern that warrants causing end users such potential issues.
In fact, user data would be considerably more secure on a properly designed, controlled system than on a user's device; How many people do you know that don't have a passcode on their phone, or have it set as their date of birth? I know a whole bunch of these types of people (and by logical extension, the passcodes to their phones).
You also mentioned that the data will be deleted from the database. How exactly will it end up back in that database in the event of a support ticket? If it's by emailing it back to you, that would be a bigger security risk because plain text email is not secure.
What you should do instead
Build a web service to sit between your app and the database
Pass the login details from the application to the web service and perform authentication/authorisation there. If successful, pass back an access token of some description. Save this access token to the database with an expire-time value.
Have the app call various api endpoints, passing the access token as part of the Authorization header (so it doesn't get cached or end up in the logs of proxies and web servers etc). If the token is valid, fulfil the request and return the requested data back to the app from the web service
On log-out/quit, have the app remove any sensitive information from the device memory if security is such a concern.
Additional Notes
As with any such design, you should ensure that all communications are done over a secure channel.
Ensure passwords are stored in a secure format and not transmitted or stored in plaintext anywhere. Use a secure channel for passwords in transit, Bcrypt is good for storing passwords or consider implementing Secure Remote Password Protocol.
Ensure that direct access to the database is only allowed from your web service and not the wider internet
Ensure that your webservice sanitises input, escapes output and is not vulnerable to SQL Injection attacks.
The benefits of this approach are obvious:
Your app data remains secure so long as the environment is secured using the correct tools. If you choose the right hosting provider they'll also be able to provide help and support securing your web server and database.
In the event of a user changing their device, logging out or whatever else they'll be able to log back in as they see fit. This will meet the already well established expectations of users and reduce potential support calls.
If you decide to expand on the features of your app later on, you can add new tables to the database, new endpoints to the webservice and new functionality within the app to consume said endpoints.
Many users tend to have a bad habit of reusing passwords; With a properly designed system you're able to audit login attempts, lock users out for a period of time after so many incorrect password attempts, force password expiry or resets and allow for self servicing of password changes to the whims of your more security conscious users.
In my Android app, I am getting the user information from server using a HttpURLConnection. Each user has a unique Id which may be accessed publicly.
Problem is if a third party, say, UserB has the Id of UserA, then they can abuse it by setting it inside my app (we know that how easy is to decompile Android APKs) then calling the server using my app and getting the output from server (including sensitive private information of UserA).
How can I prevent this from happening? What security tricks do you recommend?
Side note 1: I already have used encryption/decryption methods. But they are not going to stop UserB from abuse because when the UserB sets the Id of UserA, the app calls the server and then they have access to final decrypted output.
Side note 2: I have thought about Phone Number verification, but it is not operational for my app currently.
Side note 3: I cannot restrict the user to a specific device because they have to be able to use it on their different devices.
Side note 4: Libraries like Firebase, Gcm and the like are so secure. It would be a good idea to find out what ways they use to keep hackers from accessing another user's information!
Side note 5: Thanks to Gabor, I noticed that I had to mention that I cannot use a login interface unfortunately. If I could, that would be for sure a primary choice. It's the nature of my app and I can't change it!
That's actually a very good question and a holy grail of all security officers :)
What's I learned is that whatever you do, as long as you cannot protect the physical device against unauthorized access, there's always a risk. The problem is:
* On the one hand, you wish that the app will keep and store an information which authorizes the owner of the device
* On the other hand, you have to protect this information on the device, but because your app needs to be able for accessing it, also the accessing algorithm must be available on the device.
So I would say, there's no "clear" way. What you can do, is to make the cost of obtaining information (in your case) unprofitable.
You said that the user ID is "publicly available". That's ok, but it means that the UserID is not "secure information". I would say, that your users need to be authorized first, and then the server should generate a UNIQUE token, that will be used in replacement of UserID when calling next requests.
You can implement it in many ways, but I will recommend one way, that should be not complex for your users:
Let's assume that all your users are registered. During the registration, each user needs to provide his email, UserID (could be generated) and password. Note that registration could be done in the mobile app or on the web portal.
When the app is going to start for the first time, a user should provide hist UserID (or simply email) and password.
With the first call to the server, the userID and password should be sent to the server, and server generated a Token (unique for every first login so even if the user will use two or more mobile devices each one will use the new token).
With every next call to the server, only the token needs to be provided to authenticate the user/device.
Where to store that token? No matter. I would say in any private storage of the app. You can and should, of course, encrypt it, obfuscate a so one, but whatever you do, if one has access to the device, he can always copy it.
You will say now, that it's not 100% secure. That's right. So I would say if it could not be secure, we should minimize the risk of abuse.
There are also some ways how one can do that.
First of all, in case of abuse, your users should be informed about it. Having a token algorithm, the user can take and action, and simply disable stolen tokens.
In case if the device has been for instance stolen, your users can/should be able to disable tokens (devices) on the web portal (or in another instance of the app) after signing in using email/password authentication.
The only one problem is how to detect that the mobile device has been "cloned". In that case, the user is physically not aware of the abuse.
My guess here is to implement the following algorithm (auth pooling):
1. Let the mobile app send the "keep alive" message with the Token to the server at the certain time when the app is inactive (let's say user xyz#gmail.com should send keepalive always at 10:00, 12:00 and so one).
2. Let the app send the keep alive, with some frequency when the user is logged in (app is active).
3. These frequencies/schedules must be know for the server and app (and could be even public).
In case if the server detects the same token in keep alive nearly the same time, the user should be informed (by the different channel, it could email) about possible abuse.
* NOTE: this is only an idea, I never did that, and I'm also wondering what other things about it, but in my opinion, this is quite simple to implement, and gives you a good change to minimize the risk.
When a user starts using the app, they should log in using their credentials (eg. username and password). From the app's perspective, this is a roundtrip to the server to obtain a token. The token is then stored in the appropriate credential store for the platform you are using, and can be used to impersonate the user in further requests (the token can be sent with requests as for example an Authorize header, practically a bearer token). It also should have an expiry time, after which the user has to provide his credentials again.
Such a token can be a plain jwt you create, or it may come from something like a full oauth2 / openid connect implementation. If you decide to implement it yourself, be careful, it is not straightforward to get it right.
This way, you have proper authentication in place, you know who your users are in subsequent requests, and this way you can enforce access control rules on the server.
I have read Can In-App Purchase Prevent Software Piracy recently.
It's talking about using ssl etc. for protecting apps from piracy.
I'm planning to do something different, but i'm not sure if it's enough.
User gonna sign up for my services in app, and then when user wants to activate some paid stuff.
User will pay for it and when the purchase completed,the app will write onto sql database about activating something.
And when the app connected to internet,it's gonna get the data of whether something is activated or not,if something activated,it will enable it. My app works with internet, so most probably checking process will always work.
And i will send device properties onto server,so i won't allow user to use the application with same username and password more than 3 devices.
The Question is, is it enough? my server won't use ssl or something but sql database.
This is definitely more of a philosophical question. When it comes to security in general, there is never enough. It comes down to risk-assessment.
Your situation has three-facets:
Purchase authentication - which if you are doing it right, Google has created a practically secure solution. If you don't even call the server unless the purchase is authenticated then SSL will do nothing to help make this facet more secure.
Limiting devices - this is where you can benefit from SSL. The risk of not having SSL, is if you have someone smart enough to spoof your server and perform a Man-in-the-Middle attack. Which if that was to happen, they only gain the ability to access the content with more than the proposed 3 devices.
Content protection - if the content on the server is what the customer is paying to get access to, that can possibly be a target. Someone may try to spoof a device and access your server content. SSL may or may not help with this, depending on server-side implementation.
My two-cents*: You can spend days/weeks/months implementing a solution, or you can put a practical (less-secure) solution and focus more on your user experience. i.e. What is more important, total security or the number of users and their satisfaction?
*Unless your content needs protection because of contractual obligations.
I have read a few examples on SO for securing client / data. But we have a little bit different issue, and not sure where to look.
Basically we have an android game which is a geo-location based game. We use HMAC-SHA1 to the query string to verify that the data being sent from the client is in-fact from the client. There is a small issue. The HMAC-SHA1 key. I can obfuscate till my hearts content, but the key remains in the app. Someone can easily de-compile the app, grab the key, and then send manual queries by a browser for their user account (spoofing GPS).
I saw one example where someone suggested client & server side ssl authenication. Not sure how that would work, would you not just need to attach a ssl cert to the app? Would this not be subject to de-compiling also, it would require the end user to re-compile / use the cert?
Can we some how use the package manager to get the self signed cert? I need to find out the correct way to secure our transmission so someone can't fake their transmissions for their own user account..
Thanks
To authenticate the client, it needs some form of credentials. You can either:
don't save the credentials and have the user input them every time
save them somewhere
use system credentials
use some form of an identity provider
1 is inconvenient, 2 i subject to attacks as long as someone has physical access to the device. For 3, you could use the user's Google account so you can be (pretty) sure who they are and block them if there are any problems/attacks. 4 really a variation of 3: the user will authenticate to some third-party service and it will only issue an (temporary) access token. So if the account is compromised the token will eventually expire and/or be revoked (look into OAuth). Consider the risks and amount of work to implement and take your pick.
As for using client certificates, you can store them encrypted, so you need to provide a passphrase to use them. On pre-ICS you need to implement this yourself, on ICS you can use the system key store via the KeyChain API. You will only get access to the private key after you unlock the device (uses the unlock password/PIN to protect keys) and the user explicitly grants permission.
If you want to stick to you current way of doing things, implement the HMAC part in native code (OpenSSL, etc.), and generate the key at runtime by combining bits of it. That would make it fairly hard to reverse engineer. Additionally, you might want to add some sort of a nonce, so that requests cannot be replayed.