Ive been working on multiplayer android game that sends locally stored data to a server every minute. Then I find out that locally stored data is not secure. I could encrypt the data, but how effective will that be? The whole game is based on updating the server with user data. What should I do? My last resort would be to have everything take place on the server-side. Sorry for the choppy sentences.
You cannot trust the client. You can't trust any data stored on the client.
You can trust that people will try to hack your game.
So, just go ahead and do it server side.
Much will depend on what you are protecting. If you want to protect against cheating by your user, then, first, place a value on this cheating. If you pay money to winners, then no security on client will protect you.However, if it is just some game score, it may not worth the effort to break encryption and disassemble the application. So simple encyption may be sufficient.
Different story if you are trying to protect user data if device gets in wrong hands. Again, start with placing a value on that data. Ideally, you can just ask user for password every time app starts. Then you can use password based encryption to get the rest of information. Or you can calculate password hash and send it to server.
Related
I have an Android App where a user enters some sensitive information in the form of text. I need to store this data on a remote server, to be retrieved by that user from a different device. I want to secure this data against everyone other than that user, especially a rogue database admin - the user should be the only one capable of recovering the information.
My approach is, SALT will be generate in Android app and every sensitive data will be hashed with this SALT and will be stored for later decryption to get the actual raw data.
Is this the correct approach? or Any better approach for this?
If yes,
What if the user change the device?
How to use the same SALT in the new device as SALT cannot be saved in database?
Update: Sensitive data needs to be stored in Firebase Database.
Disclaimer
I'm not a security professional. I'm not an expert. I'm just some random developer on the internet who's done some reading in the past and took a stab at answering your question. Head over to the information security stackexchange if you want more reliable information.
A user enters sensitive information into your program. You want them to be able to recover it later, so you must save it somewhere. How to handle this?
Where to save it?
On the device if it doesn't need to be accessible from elsewhere.
On a server if the user might need to access it from a different device (or recover it).
How to secure it?
Encrypt it.
What to encrypt it with?
A standard, secure algorithm (such as AES), and a key derived from a user provided password.
But users tend to come up with poor passwords. If we're sending this to a server, and the database might be compromised, how to protect against brute force attacks?
Employ a key stretching algorithm, such as PBKDF2.
How secure is this, really?
Well if the user picks a poor password, and then your database is compromised, brute force will be relatively easy.
If the password ever leaves their device (like if you, say, reused the same password for the app to log in to your servers or something) then you're treading in dangerous waters.
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.
I want to submit non-sensitive data from a mobile app to a server.
But I don't want external sources to be able to submit data.
I would like some opinions on whether it's enough to mark the requests with hash formula.
For example:
MD5(MD5(message)+secretString)
The messages will be unique, and there is min of 10 min interval between submissions from single source (if request gets from the same source before this time, it will be rejected).
That's why I think it's not worth the effort to go for full encryption of the requests, but since I have no experience in this area I decided to check with the community.
Thanks in advance.
The approach looks good, few considerations though:
the secretString can be extracted pretty easiely for the app. The only factor here is the motiviation of the attacker.
consider replacing MD5 with SHA-1. Although there is no fatal vulnerability in MD5, the change is trivial and more secure.
don't use IP addresses for a "single source" protection. Mobile devices pass through carrier networks and share a relativly small IP block.
consider adding unique, incrementing number in the request to avoid replay attacks.
You say you want to submit data to the server but if you do a hash the data is no longer recoverable by the server. Not only the attacker but even the server will not know what the data is. Going for encryption is the best way to go about this problem if you want to achieve confidentiality.
As mentioned by another user having a fixed secret string in the app is not doing you any good as it can be recovered easily. You cannot rely on someone not knowing the "formula" reversing an app is easier than people think. So security through obscurity is definitely not the way to go. If you want to use salt use a secure random number generator but then you have the additional task to have the same salt at the server to verify (and the server needs to have the message beforehand).
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.
I am currently developing an app which downloads information from a webservice which I have written (in .net) and I want to secure the connection so that only my app can get data from the service. What is the best way of going about this?
I don't want anyone to be able to get the access details if they decompile/reverse engineer my app. Is there a way I can verify the integrity of the app that is requesting data before sending it back?
I don't care about them being able to sniff the traffic to see what it contains, I just don't want anything other than my app to be able to submit requests to protect against anyone scraping all of the data.
I'm very much a newbie in security so a simple as possible please!
Chris,
You can read on a mechanism called One Time Passwords (OTPs).
http://en.wikipedia.org/wiki/One-time_password
You can design your application to generate OTPs whenever it tries to connect to your web service. The responsibility of validating the authenticity of the OTP resides on the web service.
Let me go into a little detail now. Imagine that your app embeds in it an algorithm which generates and supplies a 256bit number whenever it connects to the web service. The web service you design also implements the validator part of the OTP. Usually OTP algorithm takes into account "Time of the day" in its implementation (I suggest google around for some Free implementations). So the server end (OTP Validator) only works if the time on Server and client is within a window (say +- n sec) of the refresh time n. Typically, the OTP validator will also generate the OTP on its end and just compare the received one. You can additionally HASH the OTP before sending and compare the HASHes of generated OTP on the server(Doesn't help or is any more secure though).
Now the question arises, what if someone gets the algorithm (may be you just use an open source OTP). Well, its meant to be. A good security implementation is only accessible with correct password, even if everything else is available to attacker. To make this, you may have to add a logic to provision your apps the first time they connect, which OTP would expect. Here I assume trust on first use. You may add some logic to store a unique resident app id that is used while calculating the OTP. Additionally, you will have maintain a mapping of "resident-id" to "public-id" on server. It is the "public-id" that you may attach to OTP and send to server to validate the app sending is indeed the one you provisioned. This requires you to map "public-id" to "resident-id" on server and then use the "provisioned-id" the same way in generating the OTP.
On top of this, you can add logic to just entertain the OTP+"public-id" combo once. This shall prevent the replay attacks in case someone just sniffs and re-sends the same request to your web service.
Hope this gives you some idea.
Ujjwal