I'm making an App with PhoneGap. I need to send some dates to an external domain that helps me to put it in a MySQL database.
I would like to create a sign that I send with my request to server, to check that these dates came from my own App. I don't want a third party to be able to make a request from outside to my external domain.
Seems to me that you need a OTP system (one time password). I've never done something like this before, but i can give you some hints on how it works.
It works with pseudo-random number generators(PRNG) that are synchronized in the client and the server. To do this, you pass a secret seed to both your PRNG (client and server side) which will generate, after a pre-determined time lapse, a random number, which will be your password during that time lapse (before the new random number is created). Since both PRNG have the same seeds and algorithms, they both generate the same random number, allowing to match the password. I hope this helps.
Related
We are building an android application and one of its features is to book a cab service provider's cab (say an Uber).
We have an application specific user ID. Let us call it AUID. To book the cab, the application would Post a request to server and send AUID along with other relevant information (like lat, long etc). How do I make sure at the server end that the request is indeed coming from the correct user and it is safe to book the cab? In the current form, if a third party gets to know the AUID of another person, the third party can book a cab on behalf of that person.
One of the solutions I thought of was using asymmetric encryption. The application would hold the public key and the server would contain the private key. Instead of sending the user ID to the server, we'll instead send an encrypted key where the key would be AUID + timestamp encrypted using the public key. We'll then decrypt the message using private key at server end to obtain the AUID. If the timestamp at server does not lie within a certain interval of the timstamp sent by the client, we reject the request.
Is this a safe enough approach? Is there any other practice widely followed for such scenarios?
What you propose is sensible: encrypt the AUID on the client app and verify on the server. As comments suggest, SSL is vital.
The problem is that if how to encrypt the AUID is in your app, it can be figured out by anyone dedicated enough.
You can drastically reduce the risks of fake requests by issuing a separate encryption key for each user. This means that if someone cracks your code, they can still only spoof from one account. However, once an attacker had decompiled your app, they could theoretically start new accounts, get a valid encryption key and spoof requests.
What you need for 100% reliability is some form of authentication which is not stored in the client app - like a password or TouchID on iOS or fingerprint api on Android M. So when a user orders a cab, they need to enter some piece of information which you also encode with the AUID and check on the server. That secret information is not stored in your app, so no-one can fake requests.
Requiring a password from a user is pretty inconvenient. Fingerprint scanning is much easier and probably acceptable. You could also use a trust system - if the user has ordered cabs before and everything was OK, they can order without special authentication. Using Trust together with individual encryption keys is pretty effective because anyone trying to spoof requests would need to do a successful order before being able to spoof - which is probably too much hassle for them.
The App could have a private key hard-coded into it and my server could have the public for it and the App could sign everything. But then a hack could identify the private key in the object code and write a malicious App that signs everything with that same key. Then that App could use my server.
The App could do a key exchange with my server but how does the server know the App is authentic when it does the key exchange?
In essence you cannot know.
Reason is simple: since anybody can get to the client and have everything the client is and knows by reverse engineering the client (to which they have all they need to perfrom that), there is nothing that can prevent them from answering any challenge you might set to what the real app would answer.
You can make it harder on fake apps though. But they could (if done right) give the answer anyway.
E.g. how to make it harder:
The server sends a challenge to the client app to calculate e.g. the CRC32 (or md5, sha-1, sha-256, ... doesn't matter as such) of the app itself from a given start to a given end. If you set those start and end points to be fully random for every challenge you send, you essentially force the fake app to have the real app's compiled code in full ... So you place the burden of having to have the real app (not forcing it to be actually running the (unmodified) code, just having the actual unmodified code).
Take care that you would need to support the server side with allowing for multiple versions of the client etc. or you can't upgrade the clients anymore.
Anybody distributing a fake app would hence be forced to violate your copyright on the real app (and your lawyers would have am easier case maybe).
Alternatives:
To pick an alternative, you need to figure out why it's (so) important to have your client ?
If the client contains secrets: remove them, make the client display only and have an 3 tier model where you only let the user run the display part and keep all secrets on your servers.
If you get your revenue from selling an app, give it away for free and sell accounts on your server. Use authentication to do that: you can authenticate users (login&password, real 2 factor authentication , ...) you can also disallow them to dramatically change their geo location in a short time, disallow simultaneous logins, ...
But the price is the hoops for the user to jump through. And they might use other clients nonetheless.
If you allow logic (like e.g. used in online games) to use the power of the user's CPU to do things, you can still keep oversight on a logic level on the server: e.g. if it takes 5 minutes at the very minimum to complete a task in the real client, and if the client reports back as "achieved" before those 5 minutes are done: you have a cheater ... Similarly, make sure all important assets are only given from the server, don't trust the clients ...
I want to authenticate my users based entirely on cookies and sql db.
What I do is:
1. Once they login, I generate a random string, create a hash from it, save it in the database along with the user id and his IP.
2. I send the hash to the user as cookie
3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
4. (As pointed by Akhil) If he clears his browser cookies or anything does not match the information on the database, I clear all the rows with his username and log him out.
Note: I use a session cookie for storing the random hash, which again is generated using the timestamp, and as long as time doesn't repeat itself(I believe), its random in the corect way.
Is this fine? How can I make it better?
Once they login, I generate a random string
Make sure you use a cryptographically secure method to generate the random string. Do not use mt_rand use something such as openssl_random_pseudo_bytes.
create a hash from it,
Make sure to use a secure hashing algorithm (not MD5, and at least SHA-2).
save it in the database along with the user id and his IP.
One thing to bear in mind is that some internet connections share IP addresses or will sometimes change the client IP address (e.g. AOL or mobile).
I send the hash to the user as cookie 3. Whenever he wants to access something, I verify if his cookie hash matches the one on the server and also if his IP matches. Of yes, he is valid or else, log him out.
It sounds like a good way of doing it and there are no flaws in itself. I would implement a session timeout mechanism. For example, store the date last used in the DB for a sliding expiration and the query will only query records that have not expired. You could have a background process that runs to clear out old, expired records.
Also, use HTTPS and set the Secure and HttpOnly flags on the cookie. This will prevent them being leaked over HTTP, but I would not go as far as disabling HTTP on your system as there are workarounds for an attacker if it is anyway.
I would not be concerned with the cookie being stolen by another user on the same machine. If the cookie can be stolen in this way then the user's machine is probably compromised anyway and you cannot make your system protect data that is outside of your control. You could however renew the token (random string) on a periodic basis giving the user a rolling cookie. You would have to ensure only one user can be logged in at once under the same account though for this to be effective.
Your method only makes sure that the user possess the random string you generated and is using the same external IP address. There exists several way of abusing this system:
if your website doesn't enforce HTTPS then a user connecting using an unsecured public WiFi network could be at risk: if another user of the WiFi network is listening to all the packets being sent on the network, he could intercept your cookie and use it to access the website as your legitimate user. Your server would be unable to differentiate them because they'll both use the same IP address... (There is a Firefox extension available which enable anyone to intercept such login cookie easily: http://en.wikipedia.org/wiki/Firesheep)
This system is also more generally vulnerable to man in the middle attacks (without HTTPS)
If your cookie is stored on the user computer's hard drive it could be reused by another user.
So to answer your question, your system can be deemed as secured provided a few conditions:
you enforce the use of HTTPS on your website (unencrypted HTTP connections should be refused)
your random string is truly random (there exist right and wrong ways of generating random strings in PHP)
your cookie has a short expiry and preferably is set as a session cookie.
You should take a look at the following related question providing details about the proper way of doing what you want to do: How to secure an authentication cookie without SSL
One cannot say this is "bad". But in Web Development, and specifically in its security domain relativity talks. I recommend you to download a CodeIgniter (google it for more info) Session Class (standalone version) and use it. The basic idea is the same as yours, but it is properly more mature since it is developed in such a famous php framework. You can do your DB operations within that class too, since it allows session saving to DB.
I have an application that runs on for example Google TV or Apple TV, which sends HTTP requests to a service of mine.
Now if someone listens in on this request, they can replay it and in that way execute a Denial of Service (DOS) attack our service.
Is there any way to make each request unique, so it cannot be replayed?
I thought of sending the time encrypted in the request and check the difference between the server time and the time the request was sent, but I'm getting too big time differences to compare.
Does anyone have a better idea?
You are in a good situation as you have control both on the server side and the client side (your application is talking). Include into your message
The current time in milliseconds plus + random number
The combined hash produced by these values plus (as a the third input) some key only your application knows. Use some good one way hashing algorithm.
Only the code who knows the mentioned key will be able to compute a correct hash. The used request records (hash and time stamp) can be stored for some expiration time that can be long. Very old request records can be easily expired as they contain the time stamp.
The positive feature of the proposed approach is it does not require to connect in advance in order to receive a token, needs no authentication, needs no registration and can use the open protocol. Using token just by itself does not help much against DoS as an attacker quickly writes a script to connect and obtain the token in advance as well.
I'm developing a mobile application for a company. Everyone at the company has an #company.com email address. The app itself is confidential, so it will only be installed on employees' devices. This app communicates with an external server to store and retrieve data.
Ideally what I would like to accomplish is to let people log in to the app by just providing their email address, without a password. Here is my current thinking:
A new user opens the app for the first time on a certain device and puts in their email address. The email address is sent to the server, along with a static token embedded in the application (which is the same for all instances of the application).
The server verifies the token and the fact that the email address is #company.com. It responds with a new token/key for use only with that user and device, which the client stores in plain text locally. That key is effectively the user's password. It is hashed, stored in the server database, and marked as disabled.
There are two possibilities at this point:
The server sends an email to that address confirming that they want to log in on a new device. The email contains a link which, when clicked, marks the key as enabled. There would need to be rate-limiting on new device requests so people can't get spammed if someone discovers the token embedded in the app.
An administrator specifically approves new device requests.
Every subsequent client request to the server must include the key.
Assuming all communication is over SSL, does this sound like a secure strategy? Is there a more secure or simpler approach?
Additionally, what is the best way to generate the token that will be stored client-side? Since I want users to only put in their email address the first time they use the app, I believe that this token will never change. Here is my current algorithm (PHP) loosely based on Drupal's drupal_get_token():
// Usage: get_token($email) or get_token($client_token)
function get_token($value = '') {
$salt = hash('sha256', 'Some static, predefined phrase');
$hmac = base64_encode(hash_hmac('sha256', $email, $salt, TRUE));
return $hmac;
}
As you can see it doesn't protect against parallel attacks (e.g. if someone figured out the predefined phrase and algorithm and they had access to the database, they could generate hashes and compare them against the ones stored in the database) but because the original key value is already long I don't think this would be nearly as effective as it would be against normal passwords. Additionally I am not sure of a way to create a dynamic salt that an attacker would not already have access to if they could access the database (or honestly if it would even matter at that point, since getting access to the database would expose the data we're trying to keep confidential anyway).
After some research and more thought, I believe that the answer to this question comes down to the vulnerability of the local storage. Since it's safe to assume in this case that only company employees will be using the app, there is insignificant risk of malicious code running in it even if there was a problem in the code that would make that possible. As a result the main risk is from some other app taking advantage of a security hole in the OS's local storage implementation to read the local private key off the disk. Since the existence of the app should not be known to anyone outside the company, it is very unlikely that this information would be directly targeted. So I think this is an acceptable process for this company.
In the general case though, anyone considering implementing a similar model should be aware of the risks of basically storing a password in plain text locally. (This is as opposed to storing a password in the user's head, or equally likely in plain text in a password file elsewhere on their machine; it's your call which is more secure.)