I've figured I have to do some kind of API where the Android app sends parameters to a php-file, or similar.
I'm thinking of an app that would have some sort of high score list. How would I go about making sure that the submitted high score values are in fact achieved through the app? Say that the person achieves 9001 points. Now if this only results in some sort of file.php?score=9001 call, I'm not feeling very secure about people finding the php-location and submitting whatever they like.
Any input on this kind of problem? Thank you.
There is no way to make this 100% secure since you have no way of verifying where a request came from, but there is a way to make it slightly harder to hack the highscores. It's still basically security through obscurity but it requires digging in to the actual app binary rather than just looking at the network connections.
First, pick a "password" for your app. Instead of sending just the score, also send a cryptographic hash (say, SHA-256 or something) of the password concatenated with the score. On the server side, recalculate the hash of password concatenated with score and check if this matches the submitted hash. If it does not, reject the score submission.
Now this is somewhat more secure than the initial approach because looking at the requests the app makes does not enable you to forge scores. However, looking in to the binary code off the app will still allow an attacker to recover the password and forge score submissions, but this is very involved and probably good enough for your purposes.
Of course, this does not rule out being able to duplicate a score (once the proper hash is known, you can submit a score as many times as you want). If you even want to prevent this, submitting a score would have to go like this: request (random) ID number from server, hash score + ID + password, submit the score + hash, the server then checks whether this hash is good. The server needs to remember the ID number so this is a little more involved to program.
A simpler solution would be to associate each score with the players name, and only allow 1 score per player. Then you could hash password + name + score.
Good afternoon!
It's better to communicate with the server via POST. So you can send an additional parameter, e.g. key, from your app to server and check it there.
The sample of PHP:
<?
$key = trim(htmlspecialchars($_POST['KEY']));
if ($key == 'your_secret_string') {
//write data to DB
}
?>
Related
I have an Android application that allows users to post information to a database, via a java web server that I have code on.
Users are allowed to up/down vote said post. How do I prevent the same user from voting a plethora of times on the same post?
A few ideas I had:
Disabling locally via adding a local storage "key" for the post ID Unique Key. For instance, when the user votes up or down. It writes a key with the information of the type of vote and the Unique Identifier of the post on the user's local storage. Is this feasible with a lot of votes? Would it cause any sort of hard drive consumption/lag?
Storing a uniquely-generated key on the user's phone generated at application install. This key would be submitted to a new table in the database that associates posts with votes and the "user-key".
If you're expecting lots of information, a database is probably the way to go. Obviously this will use storage space, but not much. Writing to the db tends to be very fast in my experience.
The unique key would work fine too. That way would be more secure (depending on how you do it) since it would be harder to spoof it from the client. If you generate the key based on the user's Google account, or the device ID, you're in good shape. If you do it by some pseudorandom method then the user could still cast multiple votes by just clearing the app data and getting a new key.
If it's really important to prevent multiple votes, do it on the server. If it's not particularly important, do whichever method seems easier to you. You can also consider doing both, for the best of both worlds: immediate feedback to the user on a duplicate vote attempt (or just altering the UI to make it impossible), plus a backup validation on the server in case the user tries to get around the client check.
I just noticed this article about a mobile app that is storing user information in plaintext. I've paid attention to the idea of storing the user's password on the server (using a SHA-512 hash function), but I'm not clear on the best methods for storage of personal information at the device itself.
Let me be clear I am essentially only talking about user names and passwords. The data that my app interacts with is not at all sensitive, and I know that I can implement some sort of symmetric encryption/decryption on that data.
For user convenience purposes, I'd like to offer the user an option to store their user name and password locally so that they aren't required to enter it each time they use the app. But I know that user's tend to reuse the same password for many different purposes, which means that I need to take precautions to keep my user's passwords secure. Classic tension between convenience and security.
Is it just simply a terrible idea to ever store this information locally? Or are there relatively simple means to securely encrypt this? Do the iOS and Android O/S provide any help with this?
Not necessarily looking for exhaustive answers, but I'd really appreciate some topics to research, article links, books, etc. Thank you very much. If this is a redundant question, please direct me to any posts that give answers that are still considered current.
Thank you very much!
All data on the device is automatically encrypted by the device to some degree, using the device id as the key. This prevents data from easily being read by anything other than the device itself, or someone with the device id anyway.
There's another level of encryption that you can pile on that utilizes the passcode, called Data Protection, which prevents the data being read unless the passcode is entered.
You can manually enable data protection in your app by using NSFileManager to access files and setting the NSFileProtectionKey attribute to NSFileProtectionComplete. See: Implementing and Testing iOS data protection.
Note that the user must set their device to require a passcode, and the stronger the passcode, the more secure the data will be.
You may be able to easily enable data protection through the provisioning profile for your app, even if you don't use the NSFileManager class with NSFileProtectionComplete. See: Data Protection / NSFileProtectionComplete - successfully supported through entitlements.plist?
I still wouldn't store the password. Store a randomly generated session key that is created when they log in. At least you can expire those and it's not the plain text password.
Just a follow up to this post from a year ago. What I decided to do was to generate a random session key (similar to #Marcus Adams suggestion) but use that value as a salt. I then concatenate that session key with the user's chosen plaintext password and store this value on the device (if the user elects to store their password). i.e, the device stores this value:
device_hash = sha256(device_salt || plaintext)
That hashed value then becomes the string that I pass over HTTP to the server for validation. On the server side, I have a different salt value stored over there. When the server receives the device hash value, it has its own salt value which it concatenates to that string, and then performs its own hash. That final hash is the password that is stored in the server database. i.e., the server stores this string:
server_hash = sha256(server_salt || device_hash))
I think that this is a viable balance between security and convenience, particularly since I am only trying to protect the password, and not trying to encrypt the actual data that gets exchanged in the normal course of the app. If the user's device is compromised, no attacker can use a rainbow table or anything like that to reverse engineer the password since it is salted. SHA256 along with the long length of the password should eliminate a brute force attack if someone were truly motivated.
Curious if anyone has any criticisms of this approach.
i want to develop an authentication web service, which can be used in an android app to login and have access to other services. So basicaly i'm sending credentials over HTTP requests and granting access to the user if everything is good. I need to secure those credentials so they cannot be intercepted by an unwanted user.
I'm using eclipse with Tomcat 7, Jersey for my rest webservices, spring and hibernate.
My webservice goes something like this
#GET
#Path("/login/{id}/{pass}")
#Produces(MediaType.TEXT_HTML)
public String login(#PathParam("id") int id,#PathParam("pass") String pass) {
String res="Null parameters";
if(id!=0 && !pass.isEmpty())
{
try {
User user = service.getOne(id);
if(user.getPass().equals(pass))
res="Success";
else
res="Fail";
}
catch (Exception e) {
res="User not found";
}
}
return "<html> " + "<title>" + "Result" + "</title>"
+ "<body><h1>" + res + "</body></h1>" + "</html> ";
}
I'm using it to test with the browser, i didn't start coding the client yet.
I'm really scratching my head here, i've been looking around the web, some are talking about OAuth 2.0 and others about HMAC, and i don't know which one to use, and if there is another methode please let me know.
If you know a helpful tutorial about how to implement security to my project it would be great, any other suggestions are welcome. Many thanks
It really depends on the level of security you need, for your application.
There are a lot of complicated security systems, but for most applications these are quite overkill.
If you're simply looking for some basic protection of passwords, without dealing with payments or really sensitive data you could do the following simple things.
If you can, move your service to work through https. All data will get automatically protected by that already.
Hash the password. A lot of languages have build-in support already for simple hashing such as MD5 and SHA1, if not you can google their implementation, they are often used.
This means that not even you as admin know the real password. You simply save the hashed pass in your database, and compare hashes.
In your client-side, add a salt to your hashing. Probably if you google step 2, this will already be in there but otherwise it simply means that you do something like hash("132rjfASDF!"+password"+vnsadfr1!Z"); to make it even more random.
These simple steps can be achieved pretty easily and fast, and will provide your service all the security it needs most of the times.
If you're really dealing with things such as payments and sensitive data, you should look into more serious solutions.
ps. Don't think that using 'post' instead of 'get' is any kind of security and it really doesn't matter which you use for this, from an Android point of view. People will have to use a program to fetch network connections anyway to see the link come by (per example WireShark) and in that reading GET parameters is just as easy as reading POST parameters.
There's a fair bit of confusion in some of the above answers, and indeed the question itself. Some notes:
First off, REST is meant to be stateless. As such you should not have a 'login' function that sets some sort of server-side flag but instead should pass credentials with each and every request
Handling the credentials should be done in Jersey in a filter rather than in the individual resource methods. There are various examples on Stack Overflow that show this
If you are storing passwords on your server then use BCrypt to hash them. Bcrypt allows you to dial up the time taken to calculate a hash, so gives some measure of future-proofing against Moore's law
You should use HTTPS for all communications. It gives you another layer of security and protection for cheap (programming-effort-wise, anyway)
If you want to protect the information in your request against tampering then you should look at something like Hawk. This gives you the ability to protect your request headers and body against tampering, and can also work as an authentication mechanism as well
There is a lot more to securing your REST endpoints properly, but if you follow the above you'll have hit the major points.
usually username and password are sent thorough post request which hides it from user.. which is good incase some one standing over your shoulder and if they could see the url then they could see your username and password... other than that use SSL on server side..
I have seven virtual products in my game and would like to give one away each day or so to people who visit my website.
Bob Smith is correct that this will work, but depending on the value of these in-app-purchases you may want to err towards something more complex.
If there's nothing generated about these codes, i.e. my code is the same as yours, then any one person can just give this code away and it will work for everyone. Another suggestion to keep in mind is to make the code a hash of some predetermined secret value, and the unique identifier of the app.
For example, if every app has in it an ID, your code might be:
md5(userId.toString + mySecret);
Because a hash is one way, nobody can get your secret back out and compute their own codes. They have to submit their app code through your service to get a code specific for them.
You can continue to layer in features too. You could include secret identifiers for each purchase, so that one algorithm generates unique codes for each purchase.
Of course, if there is only one secret, it would also have to be hard coded into the app, which is not utterly secure. This is a problem for both Bob's system and mine, and should that secret get public the entire system falls apart. You could look into all sorts of different encryption techniques to come up with more and more clever systems, if you need that level of security.
Yes you can do that, what you should do is send the recipient of the code the code via email or someway, then in the app have a spot where the person can enter the code in. Similar to entering in cheat codes in a videogame. If their code they enter matches one that you made valid, you should grant them access to the virtual product.
In my Android application, the user can submit content to the database which can then be seen by all the other users as well.
This new content is sent to the server via GET request:
http://www.example.org/API.php?newContent=helloWorld
The problem is: If a user finds out what this URL looks like, he could easily sent malicious requests in his browser and circumvent the Android application. Maybe one could decompile the app and find out about the URL.
How can I protect access to this URL and prevent users from accessing this API directly?
Is it a good solution to generate a hash in the application and compare it with a hash generated in the API.php file on the server?
Couldn't one find out how the hash is generated when decompiling the application?
Thank you very much in advance!
So the only way to truly protect that URL is by requiring all requests to it be authenticated.
One way to do this is change your request to a POST request and send along some sort of auth token (a simple hash will do) with the request. If the auth token isn't present, simply don't respond to the request. The hash would be something you'd hardcode into both the client and server.
Now the question is how to hide your auth token. As long as you're not open sourcing your code, the only way for someone to get at it would be to decompile your program as you mentioned. To guard against this you might want to look into using proguard (http://developer.android.com/guide/developing/tools/proguard.html).
Something to keep in mind is that this method contains a single point of failure. If your auth token is ever exposed, you're done for (e.g. the HD DVD AACS cryptographic key debacle).
One other way to authenticate is on a per-user basis. As long as a valid user is making a request, you shouldn't really care whether or not the request is coming from the web browser or android app. I think this is a much better way of doing things. By doing this, you can throttle requests on a per-user basis. This however requires you to manage user profiles and the whole can of worm that comes along with it.
All that said, at the end of the day though you shouldn't really care if somebody knows the url to a portion of your API. I don't know your particular use case, but there's got to be a way to design your API so that you don't care how you're getting your requests. Also, if your doing a true GET, then you shouldn't be changing anything on the server. This means that all the 'malicious person' can do is get data off of it. This severely limits the damage they can do. In fact, unless you have sensitive data that you don't want certain people to look at, you don't really have a problem at all. If you do, then you should really think about my per-user authentication solution.
Don't trust the client for validation. This is true if its javascript in a web-browser or even some locked down platform like the Iphone.
If the app can make the API calls, then clearly everything needed to make those calls is on the phone ( secret, hash function, API key, whatever), then someone can always dump the phones storage and get all that data. They can then make whatever request they want.
What you want to do is authenticate the user and then validate the input on the server side.
Use SSL (HTTPS) for your data transfers. The exchange is encrypted before any data is sent, so anyone listening in won't be able to see either the URL or data that is sent to the server. To verify this for yourself, install Wireshark on your dev system and load the URL into a browser. You'll not see any data in the clear (either the URL or the data that is sent via either GET or POST).
You could use a somewhat confusing java method to obfuscate every letter of the URL. So kind of creating your own dictionary in a way which could make the URL possibly appear as 123.3*15*13 or something like that if someone did decompile the APK, they would have no idea. And on that note, you would ideally use Proguard to obfuscate it, so your obfuscation would make no sense to someone trying to reverse engineer.
You could make a short java method like this:
public String confuseString() {
Stringbuilder sb = new StringBuilder();
//your real URL would be abc.com, but in the app you have myURL = 123.3*15*13
//With what I'm saying the * would precede a 2 digit number that represents 1 letter
for (int i = 0; i < stringLength; i++){
String letter = myURL.charAt(i);
if (letter.equals("1"){
letter = a;
sb.append(letter);
} // you would go one to code each character into a letter
}
}
There would be several more if statements of course, but it would allow you to obfuscate your url without making any server side changes. And if you use Proguard, then that entire method that you create would make absolutely no sense to someone trying to reverse engineer.
You could of course make your obfuscation much more complicated than what I suggested, but it's an idea anyway.
Basically you'd be encrypting the URL in a very confusing fashion.
Here is an answer which may be a better method of encryption or at least give additional encryption:
Java - encrypt / decrypt user name and password from a configuration file