Minimising the value of database - android

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.

Related

How to avoid interceptions of the connection to the server in Android?

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.

A "reasonable" security model for Android app and REST

We are getting started with developing an android app and the corresponding REST APIs and I need to figure out a security model for the same. I've close to zero experience with designing secure systems and would like some expert opinion on the loopholes of a first draft we've come up with.
I've been all over the web for the past few days and everyone seems to suggest HTTPS and OAUTH as the proven answer. Since our app doesn't deal with anyone's bank account, I think we can live with less than DoD grade security (although even they get hacked often!). And we don't want to spend the effort for OAUTH unless there really is no other reasonable alternative.
We're trying to avoid HTTPS because the app will, at times, be polling the server every few seconds and we thought it'd be too expensive to use it for all REST calls. Also, the payload for some of those API calls can be too big (2-4 KBytes) for asymmetric encryption.
Here's what we've lined up so far:
User creates an account by entering a unique 'username' and a 'password' on the registration page in the app
The 'username' is stored in plaintext in SharedPreferences using MODE_PRIVATE
The SHA-256 of the 'password' is also stored in SharedPreferences using MODE_PRIVATE
The user credentials ('username' and hashed 'password') are sent to the server using https://
The server creates an authentication "token" (a random AES key, really, using a CSPRNG), stores it in its DB and also sends it back to the client (using https, of course)
The AES-256 key is then stored by the app in the SharedPreferences using MODE_PRIVATE
All further communication between the app and the server is done over http:// with encrypted (payload (json/xml) + timestamp + checksum/hash) (CBC with random IV)
The AES key is only updated if the user changes his password
For actions that require additional security, the app asks the user to re-enter his password which is verified against the stored hash
The app should be usable offline (It can talk to pre-registered embedded devices over a WiFi connection. Security over WiFi is another story!)
I know some of the pitfalls of the system already:
Storing the key on the phone isn't safe: If a hacker gets access to the user's phone, the user just needs to change his password and everything will be safe.
Storing keys on the server is bad: A lot of people seem to say if you really have to store the keys, at least store them on a separate server. But that adds an extra round trip between the servers for every REST call. And there can potentially be many of them when the app is polling.
Keys without expiry are bad: I can't think of another way to let the app function offline.
The real questions now are:
What are the other loopholes that I've missed so far?
What kind of effort would it take for someone to break into the system?
Most important of all, how can we improve overall security to some "reasonable" standard without overdoing it?
This is not DoD security!
You really do need to use https and insure it is setup for TLS 1.2 and Perfect Forward Secrecy. Additionally the app needs to pin the certificate.
Section 1:
3: Do not use SHA256, use PBKDF2, crypt of another hash that has an increased work factor.
4: Send the password, not the hashed password to the server, the server does the hashing.
7: When using https there is no need to encrypt the payload, that is what https does.
Section 2:
2: When storing keys on the server keep them out of any http accessible directory. This is a weak point and needs to be addresses with server security.
Section 3:
Use two factor authentication for administration of the server. Have a good scheme to control the 2nd factor, I like hardware tokens and keep track of them by their serial numbers. That way there is a limited number and they can be recovered when someone is no longer should have administrator access. They can also be loaned for short periods of time.
You also need to have disaster plans for various contingencies, do not wait for an incidence and try to deal with it on the fly. Some times appropriate immediate action is required.
All of this is basic.
You need to evaluate potential threats, attackers and the value to an attacker or user.
If you care about security and are not a domain expert hire one for advice and review, I do.
Aside: DoD security: Two guard stations, two overhead passages between buildings, the last building has one door that is a huge safe door and there are no windows. Ceiling bubblegum lights rotating when there are un-cleared personal in the building, one escort per un-cleared person who follows you everywhere including into the bathroom, multiple sensors in the ceiling, tempest shielding.

Secure way to store sensitive information in Android

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.

Restrict access to server backend

I'm making a cross-platform application on Monodroid/MonoTouch, and my application should contact with server-side part to get data from it. Data is sensitive and is the base of application.
How would i defend it to restrict usage of server-side from other people/applications, assuming people can get correct request syntax or if i encode my query with secret key they can get that key by debugging.
You'll need confidentiality in your data transfers, e.g. using SSL/TLS, like HTTPS, but that alone won't be enough. By default it means that the client can ensure it trust the server, not that the server can trust the client (and that does not cover your debugging case).
So you'll need authentication as well. That's nearly identical to having a secret key except that it needs to be user (or the entity you trust) based, not hard coded into the application itself (that can't be trusted).
Having the users register and get passwords (or a user-token saved to the device storage) is one way to start this. It will protect your from other people using your data.
You can enhance this by creating some kind a user/device association so that a user secret can't be shared across several devices... that can limit the possibility of using an alternative (untrusted) application by the same (trusted) user, e.g. on a different device.

How can I manage in-app billing transactions on an external server securely?

I'm attempting to implement a system for upgrading/unlocking various features of my app using "managed" purchases with in-app billing, and I'm getting bogged down by the lack of in-depth documentation or examples.
My app's purpose is to retrieve/parse and display data from my own server, and the documentation on http://developer.android.com/guide/market/billing/billing_best_practices.html states:
If you are using a remote server to deliver or manage content, have your application verify the purchase state of the unlocked content whenever a user accesses the content.
My question is, what is the best way to go about this in terms of actual workflow?
As far as I can tell, on successful purchase I would store the purchase information on my server as well as locally in the app. When the app runs, I would send the order ID to my server and the server would check to see if the order is valid (firstly checking that the order exists in my server's database, and secondly checking if I have not manually revoked the order for whatever reason).
If that is verified, the server would send a response to the app that the requested features are "licensed", and the app would provide the unlocked features/content to the user.
The obvious problems I can see with this are:
A rooted user could easily just alter the local app's SQLITE database (or whatever other method I use to store order information) to inject a valid order ID.
If network access is down, or my server is down, I still want the app to be able to run (with cached data) with all the user's purchased features.
Potential ways around the first problem that I can see involve sending some sort of device identifier with the verification request, and monitoring that at my server's end - revoking the order if a large number of devices are accessing the order in a short period of time.
For the second problem, I can't figure out an adequate solution. I initially thought that each time the verification is successful, the time this verification took place would be stored. Then, the app would continue to run with the unlocked features for say, 48 hours after the last successful verification. The issue with that is, how can I securely store this time value? Again, rooted users could simply alter the value and the app would be none-the-wiser.
Has anyone designed a server-based system for managing in-app billing purchases and can offer some suggestions?
Google Licensing provides a way to allow a cached 'You're license is valid' response to stay alive.
Application Licensing
You can also encrypt the data your are storing. If they have paid for it, they get to decrypt it. If no network access available, then implement a similar caching scheme as Application Licensing (currently licensed under the Apache License, Version 2.0).

Categories

Resources