Which one method is safer: save password in device or use token? - security

We are making an app on android and iphone. One method is to save password hash in local device and login remote server every time (with token). The other method is to login once and then get the token to communicate with server. The app save the token in device, so if user don't logout manually, the token won't expire.
Some teammates think the latter method is better instead of saving password hash in local device. But I think keep token is also unsafe. Could anyone please give us some suggestion?

We probably need a little more detail to evaluate what you're considering. Either could in theory be built well. There are several things to consider.
First, it is best to have your authentication token expire periodically. This closes the window on stolen tokens.
Authentication should always be challenge/response in order to avoid replay attacks. You should generally not send the token itself. You send the response to a challenge that proves you have it.
Of course you start with TLS as a transport layer. Ideally you should validate your certs. Together, this alone can protect against a wide variety of attacks. Not all attacks; TLS is not magic security dust, but it does provide a very nice "belt and suspenders" defense in depth.
It's interesting that you're saving the "password hash." How are you using this and how are you salting it? In particular, if many people have the password "password1", will all of them have the same hash? Without TLS, this can open you up to significant problems if you're sending the hash itself across the wire.
On iPhone, you should store sensitive credentials in the keychain. SFHFkeychainutils makes a decent wrapper around the keychain (I've got my beef with it, but it's ok). Unfortunately, I don't believe Android has a similar OS-provided credential store. (No, iPhone's keychain does not protect against all kinds of attacks, but it does provide useful protections against certain kinds of attacks and is worth using.)
You want your protocol to make it possible to deauthenticate a device that has been stolen. That could take the form of the user changing the password, or revoking a token, but the user needs a way to achieve this.
Again, it's hard to evaluate a broad, hypothetical security approach. Tokens or passwords in the protocol can each be fine. What matters is the rest of the protocol.

The way to analyze this is to assume that nothing on the device is safe. The question then becomes, what's the worst that can happen if (when) the device is compromised. If you save a token, then the user's credentials are safe and you can implement a method on the server of revoking a token. If you save a password hash, then (if I understand what you mean by this) the user will need to change passwords (and possibly a token needs to be revoked).
Also, if you tie the token to some sort of device identifier, then it would be harder to use the token from other devices. A password hash (unless it also included data about the device) would not be as hard to use on other devices. (These attacks would be available between the time the device was compromised and when corrective action was taken at the server.)
As you might guess, I agree with your colleagues about which of these two approaches is better. (I also should make clear that I don't think either of these is the most robust approach. You might want to do a little research -- search for mobile application security to find a lot of information about different approaches.)

Related

Secure web programming - Best practises in authenticating users

Getting into web development and would like to become good at making secure websites. Any general typs/answers to any of the below would be greatly appreciated.
So got some questions on the authentication side of things:
How should the password typed on the client be encoded and sent to the server - assuming https is already in use? i have heard of some suggesting that only the hash is sent for security for example. Should it be encrypted client side - how?
Similar but on server side. How should the passwords be saved. Actual, hash, etc? Should they be encrypted - how?
Also, is there a kind of architecture that can protect the passwords in such a way that if one password is compromised, not everyone else's is? For example, if all passwords are stored in one file then access to only this one file would compromise every user on the system.
if only hashes must be stored - how to handle collisions?
Once authenticated should you just rely on session IDs to maintain authenticated status throughout? I have read on tips to reduce session highjacking and was therefore wondering whether it is a good idea/the only idea in the first place for keeping users authenticated.
Is there a safe way to provide an autoLogIn feature so that the browser remembers the password - similar to social network/web-email clients?
-------------
Extra - preventing attacks
Are there any tools or even just some common practises out there that must be applied to the username/password entries provided to prevent injection or any other kind of attacks?
If I use a Java development environment (using PlayFrameWork btw) how likely is it in general that attackers could include harmful code snippets of any kind in any form entries?
PS
As mentioned I will probably be using the Java PlayFrameWork to encode the website - can you suggest anything I should take into account for this?
Any tips on design patterns that must be followed for security purposes would be helpful.
Many Thanks
PPS
You could suggest passing the job on to an expert but if possible I would like to have some experience coding it myself. I hope that this is a viable option?
Will probably like to set up an e-commerce system FYI.
How should the password typed on the client be encoded and sent to the server - assuming https is already in use? i have heard of some suggesting that only the hash is sent for security for example. Should it be encrypted client side - how?
It should not be sent to the server in a way that can be recovered. The problem with SSL/TLS and PKI is the {username, password} (or {username, hash(password)}) is presented to nearly any server that answers with a certificate. That server could be good or bad.
The problem here is channel setup is disjoint from user authentication, and web developers and server administrators then do dumb things like put a plain text password on the wire in a basic_auth scheme.
Its better to integrate SSL/TLS channel setup with authentication. That's called channel binding. Its provides mutual authentication and does not do dumb things like put a {username, password} on the wire so it can be easily recovered.
SSL/TLS offers nearly 80 cipher suites that don't do the dumb {username, password} on the wire. They are Preshared Key (PSK) and Secure Remote Password (SRP). Even if a bad guy answers (i.e., controls the server), the attacker cannot learn the password because its not put on the wire for recovery. Instead, he will have to break AES (for PSK) or solve the Discrete Log problem (for SRP).
All of this is covered in great detail in Peter Gutmann's Engineering Security book.
Similar but on server side. How should the passwords be saved. Actual, hash, etc? Should they be encrypted - how?
See the Secure Password Storage Cheat Sheet and Secure Password Storage paper John Steven wrote for OWASP. It takes you through the entire threat model, and explains why things are done in particular ways.
Once authenticated should you just rely on session IDs to maintain authenticated status throughout?
Yes, but authorization is different than authentication.
Authentication is a "coarse grained" entitlement. It asks the question, "can a user use this application?". Authorization is a "fine grained" entitlement. It answers the question, "can a user access this resource?".
Is there a safe way to provide an autoLogIn feature so that the browser remembers the password - similar to social network/web-email clients
It depends on what you consider safe and what's in the threat model. If your threat model does not include an attacker who has physical access to a user's computer or device, then its probably "safe" by most standards.
If the attacker has access to a computer or device, and the user does not protect it with a password or pin, then its probably not considered "safe".
Are there any tools or even just some common practises out there that must be applied to the username/password entries provided to prevent injection or any other kind of attacks?
Yes, user login suffers injections. So you can perform some filtering on the way in, but you must perform HTML encoding on the output.
Its not just username/password and logins. Nearly everything should have some input filtering; and it must have output encoding in case its malicious.
You should definitely spend so time on the OWASP web site. If you have a local chapter, you might even consider attending meetings. You will learn a lot, and meet a lot of awesome people.
If I use a Java development environment (using PlayFrameWork btw) how likely is it in general that attackers could include harmful code snippets of any kind in any form entries?
Java is a hacker's delight. Quality and security has really dropped since Oracle bought it from Sun. The more paranoid (security conscious?) folks recommend not signing any Java code because the sandbox is so broken. That keeps a legitimate application properly sandboxed. From http://threatpost.com/javas-losing-security-legacy:
...
“The sandbox is a huge problem for Oracle,” Jongerius told Threatpost.
“Everyone is breaking in. Their solution is to code-sign and get out
of the sandbox. But then, you have full permission to the machine. It
doesn’t make sense.”
Its too bad the bad guys didn't get the memo. They sign their code the malware and break out of the sandbox.
Any tips on design patterns that must be followed for security purposes would be helpful.
You also have web server configurations, like HTTPS Only and Secure cookies, HTTP Strict Transport Security (HSTS), and Content Security Policies (CSP), Suhosin (hardened PHP), SSL/TLS algorithms, and the like.
There's a lot to it, and you will need to find the appropriate hardening guide.

Mobile API Security Paradigm

I've coded the mobile api using Node.js, Redis & MongoDB. However right now I am looking for a concrete way to provide security in our system. The question I have inspired by the infamous principle of Auguste Kerckhoff;
"It must not be required to be secret, and it must be able to fall into the hands of the enemy without inconvenience"
After inspecting this principle I figure out that there is no safe way to secure data after a sniffer capturing the entire data package. Of course there are alternate ways like using an API key, using encryption algorithms like MD5 & MD6,Triple DES,SHA1 etc. However this also won't work if the entire data package is captured. And there is security precaution standarts like HTTPS, SSL certificates. However again if someone with talent captures the data package it can act just like a verified user in our system.
How would it be possible to apply a security method such that even though the entire data package is captured, the system would be able to distinguish the request coming from an outer source not from our verified user.
PS: I thought that applying a custom encryption algorithm with timestamp in order to prevent this problem could be a bit chaotic.
According to Kerckhoffs's principle "A cryptosystem should be secure even if everything about the system, except the key, is public knowledge." So the way cryptosystem, works is that the key is the only thing that can be used to decipher the system. If the key is fallen to the enemy then its all over.
In practice when you communicate over the internet or try to
authenticate your email account with the password. Your password is
never sent to, nor stored on the server in plain text. If you do then,
its not secure. The best security practice is not to store the
password at all (not even encrypted), but to store the salted hash of
the encrypted password.
That is one hash for one user. It is one way, you cannot get back user info, just test if it is in the database or not. Now even if the enemy takes control of the database, it cannot access your username/passwords.
Now coming to the point, it does not matter what you transmit in the communication channel, because the communication channel is the enemy!!! It is available to other users, anyone can sniff it. It is like enemies scanning each other on the radio.
The hash that has been sent over the channel can be sniffed and be used for authentication. True, but server can differentiate between spoofed attempt and the actual attempt, using HTTPS connection. Server tracks the HTTPS sessions and would ask to revalidate if something like this happens. HTTPS blocks use of sniffed data / MITM attacks. Even if sniffer gets hash (temporary ticket), he cannot do anything malicious, username and password cannot be cracked.
Thanks to Kerckhoff, our passwords are safe.
How to implement it on node.js ?? look for passport.js package. It implements the current standard OpenAuth.

Login system, security

I need to make a log-in system and having basically no previous knowledge of how it's done (with security in mind) I studied it on the internet. The way I would do it now is something like this:
Server has login information in a database table - username and a password hash per user (encrypted with SHA224 for example).
When client wants to authenticate, password is encrypted with SHA224 (client-side) and sent with username to the server to verify a match in the database.
If the user ticked "Remember me" option, an authentication key is generated on the server, inserted into a database along with the IP of the client.
The authentication key is sent to the client and stored in cookies.
Now, when the client returns, authentication key from cookies is sent to the server, the server finds it in the database and checks if the IPs match as well. If it does, the user is authenticated and a new authentication key is generated and sent to the user (and stored in cookies) for next visit.
My questions are:
How does encrypting password make this any safer? The hash still can be captured on the way from client to server and misused just as well as if it was plaintext. I know that this is an elementary question but I somehow couldn't find an answer to this one.
Is this security system secure enough? (or better yet - Did I get it right?)
Why does hashing a password make the system more secure
Hashing is not equal to encryption. Encrypted data can be decrypted back into plain text. Hashed data cannot be decrypted.
By hashing your user's passwords, nobody can see what passwords are used. So if your data gets stolen, the hashes cannot be decrypted by the hacker. The same goes for the system administrator, he/she cannot 'lookup' a password. This can be an all to common scenario in shared hosting environments.
Storing passwords
The easiest way to get your password storage scheme secure is by using a standard library.
Because security tends to be a lot more complicated and with more invisible screw up possibilities than most programmers could tackle alone, using a standard library is almost always easiest and most secure (if not the only) available option.
The good thing is that you do not need to worry about the details, those details have been programmed by people with experience and reviewed by many folks on the internet.
For more information on password storage schemes, read Jeff`s blog post: You're Probably Storing Passwords Incorrectly
Whatever you do if you go for the 'I'll do it myself, thank you' approach, do not use MD5 anymore. It is a nice hashing algorithm, but broken for security purposes.
Currently, using crypt, with CRYPT_BLOWFISH is the best practice.
From my answer to: Help me make my password storage safe
As for the infamous remember me option.
Create a random token and give it to the user in the form of a cookie.
If the user presents a cookie with this token, you give them access. Key is to only accept each token once. So after it is used, replace it with a new random token.
This token is, in essence, just another password. So in order to keep it safe, you do not store the token, but a hash of it. (just as you did with the password)
Your suggestion of binding the cookie to an IP-address will unfortunately not work. Many people have dynamic IP-addresses, some even change from request to request during a single session. (this is for example caused by load-balancing proxies).
Sending passwords to the server
The only method currently usable for sending a password from a web browser to server is by using a SSL-secured connection. Anything else will not be safe, as you cannot guarantee the integrity of the solution on the client side.
Some points I want to add:
the hashing of the password is not done on the client. You cannot do it reliably. The necessary technique for computing the hash (JavaScript in your case) might not be available and you cannot trust the result. If somebody can retrieve the hashes of the passwords in your database he could just login without knowing the actual passwords.
make sure to use SSL or another secure transport for transmitting the given passwords from the client to the server. SSL is a good idea for everything after all.
you should not use a single hash algorithm for storing the passwords in the database. Have a look at HMAC. That is far better. Additionally read about salts in cryptography.
Never ever invent your own crypto
mechanisms. Use someone else's.
Crypto is beyond tricky, and unless
you're Bruce Schneier, you have an
extremely slim chance of improving
it, while having a huge chance of
screwing it royaly.
Do not encrypt passwords, hash them.
If you're using hashes, salt them.
If you don't have
to use straight hashes, use HMAC,
they're much more resistant to
precalculated attacks.
If you're
sending stuff across an unsecure
link, add a NONCE to the transmission
to prevent replay attacks. This goes
for both client->server and
server->client.
If you're using salts and nonces, make sure they have high entropy. 'secret' is not a good one. Make it random, make it long, make it use large character sets. The extra computation cost is minimal, but the security you gain from it is enormous. If you're not sure how, use a random password generator, and then use ent to measure entropy.
Do NOT use a
timestamp as a nonce, unless you have
a very specific need and really know
what you're doing.
Use session
protection. SSL isn't perfect but
it's helluva better than nothing.
If you're using SSL, make sure to disable weak protocols. SSL session starts with 'offerings' of lists of ciphers both sides can do. If you let clients use a weak one, an attacker will definitely use that.

Secure authentication on a device occasionally without connection to a server

I am working on a server application which will have quite a fair number of client devices accessing it.
The problem is we cannot guarantee that the client devices will always have access to the server. It is perfectly possible for a device to be outside the network for 1 week or more. In the meantime, we still want the device to work in an autonomous manner with a copy of the necessary content (automatically updated when connected to the network).
Of course, this is causing some security issues related to the user authentication. We plan to have the device have a copy of the users list. We are pondering on how to have the authentication secured on the device. Obviously we cannot send the passwords in plain text in the update packages.
Passwords on the main server are salted and hashed and we are thinking of using a hash of some sort (SHA1 ?), for the list available to the client device.
By doing so however we are lowering the bar for attacks on the devices (no salt).
Would you have any suggestion for an efficient way to keep the client devices as secure as possible?
Thanks!
First of all, you need to be clear who the attacker is. In this case, what if someone where to steal the device? Another scenario is what if someone where to connect to the server with a malicious client? What if someone where to sniff the traffic?
To stop sniffing all communication should be done over ssl (probably https). To prevent malicious clients you can identify each client device by a SSL certificate hardcoded and store these credentials on the server side in a database. The server could use a normal certificate from a CA. If a device is stolen you could revoke the certificate in your local db. A full PKI isn't necessary, although this is a case where one could be used with great results.
Spilling the password hashes to the attacker(client) is always a vulnerability. Transferring all of the password hashes to the client is commonly done with sql injection. This is not a solution.
md5 is broken in many different ways and exploited in real world attacks. sha1 is more secure and still approved by NIST, however sha256 is a very good choice. Salting password hashes with a random value is necessary.
A secure solution that I can think of for your password problem is to only allow authentication while connected to a network. That user could be cached and then that user could log out and log back in. This limits the attack scenario but doesn't negate it. If someone where to steal the device he would also have a password hash, in this case the user must be forced to change his password (and hopefully this happens before the attacker has a chance to break the hash).
A less secure solution would be to use a heavy hash function such as PBKDF2. This is used in applications like winzip where the password hash is always available to the attacker. The drawback is its EXTREMELY SLOW and can't be used for normal web applications because of this.
If you don't have a good reason to weaken passwords on client device, use the same auth scheme on client and server. Client devices can handle salt too.

Signed session cookies. A good idea?

In an effort to increase performance, I was thinking of trying to eliminate a plain 'session cookie', but encrypt all the information in the cookie itself.
A very simple example:
userid= 12345
time=now()
signature = hmac('SHA1',userid + ":" + time, secret);
cookie = userid + ':' + time + ':' + signature;
The time would be used for a maximum expirytime, so cookies won't live on forever.
Now for the big question: is this a bad idea?
Am I better off using AES256 instead? In my case the data is not confidential, but it must not be changed under any circumstances.
EDIT
After some good critique and comments, I'd like to add this:
The 'secret' would be unique per-user and unpredictable (random string + user id ?)
The cookie will expire automatically (this is done based on the time value + a certain amount of seconds).
If a user changes their password, (or perhaps even logs out?) the secret should change.
A last note: I'm trying come up with solutions to decrease database load. This is only one of the solutions I'm investigating, but it's kind of my favourite. The main reason is that I don't have to look into other storage mechanism better suited for this kind of data (memcache, nosql) and it makes the web application a bit more 'stateless'.
10 years later edit
JWT is now a thing.
A signed token is a good method for anything where you want to issue a token and then, when it is returned, be able to verify that you issued the token, without having to store any data on the server side. This is good for features like:
time-limited-account-login;
password-resetting;
anti-XSRF forms;
time-limited-form-submission (anti-spam).
It's not in itself a replacement for a session cookie, but if it can eliminate the need for any session storage at all that's probably a good thing, even if the performance difference isn't going to be huge.
HMAC is one reasonable way of generating a signed token. It's not going to be the fastest; you may be able to get away with a simple hash if you know about and can avoid extension attacks. I'll leave you to decide whether that's worth the risk for you.
I'm assuming that hmac() in whatever language it is you're using has been set up to use a suitable server-side secret key, without which you can't have a secure signed token. This secret must be strong and well-protected if you are to base your whole authentication system around it. If you have to change it, everyone gets logged out.
For login and password-resetting purposes you may want to add an extra factor to the token, a password generation number. You can re-use the salt of the hashed password in the database for this if you like. The idea is that when the user changes passwords it should invalidate any issued tokens (except for the cookie on the browser doing the password change, which gets replaced with a re-issued one). Otherwise, a user discovering their account has been compromised cannot lock other parties out.
I know this question is very old now but I thought it might be a good idea to update the answers with a more current response. For anyone like myself who may stumble across it.
In an effort to increase performance, I was thinking of trying to
eliminate a plain 'session cookie', but encrypt all the information in
the cookie itself.
Now for the big question: is this a bad idea?
The short answer is: No it's not a bad idea, in fact this is a really good idea and has become an industry standard.
The long answer is: It depends on your implementation. Sessions are great, they are fast, they are simple and they are easily secured. Where as a stateless system works well however, is a bit more involved to deploy and may be outside the scope of smaller projects.
Implementing an authentication system based on Tokens (cookies) is very common now and works exceedingly well for stateless systems/apis. This makes it possible to authenticate for many different applications with a single account. ie. login to {unaffiliated site} with Facebook / Google.
Implementing an oAuth system like this is a BIG subject in and of itself. So I'll leave you with some documentation oAuth2 Docs. I also recommend looking into Json Web Tokens (JWT).
extra
A last note: I'm trying come up with solutions to decrease database
load. This is only one of the solutions I'm investigating
Redis would work well for offloading database queries. Redis is an in memory simple storage system. Very fast, ~temporary storage that can help reduce DB hits.
Update: This answer pertains to the question that was actually asked, not to an imagined history where this question was really about JWT.
The most important deviations from today's signed tokens are:
The question as originally posed didn't evince any understanding of the need for a secret in token generation. Key management is vital for JWT.
The questioner stated that they could not use HTTPS, and so they lacked confidentiality for the token and binding between the token and the request. In the same way, even full-fledged JWT can't secure a plain HTTP request.
When the question was revised to explain how a secret could be incorporated, the secret chosen required server-side state, and so fell short of the statelessness provided by something like JWT.
Even today, this homebrew approach would be a bad idea. Follow a standard like JWT, where both the scheme and its implementations have been carefully scrutinized and refined.
Yes, this is a bad idea.
For starters, it's not secure. With this scheme, an attacker can generate their own cookie and impersonate any user.
Session identifiers should be chosen from a large (128-bit) space by a cryptographic random number generator.
They should be kept private, so that attackers cannot steal them and impersonate an authenticated user. Any request that performs an action that requires authorization should be tamper-proof. That is, the entire request must have some kind of integrity protection such as an HMAC so that its contents can't be altered. For web applications, these requirements lead inexorably to HTTPS.
What performance concerns do you have? I've never seen a web application where proper security created any sort of hotspot.
If the channel doesn't have privacy and integrity, you open yourself up to man-in-the-middle attacks. For example, without privacy, Alice sends her password to Bob. Eve snoops it and can log in later as Alice. Or, with partial integrity, Alice attaches her signed cookie to a purchase request and sends them to Bob. Eve intercepts the request and modifies the shipping address. Bob validates the MAC on the cookie, but can't detect that the address has been altered.
I don't have any numbers, but it seems to me that the opportunities for man-in-the-middle attacks are constantly growing. I notice restaurants using the wi-fi network they make available to customers for their credit-card processing. People at libraries and in work-places are often susceptible to sniffing if their traffic isn't over HTTPS.
You should not reinvent the wheel. The session handler that comes with your development platform far is more secure and certainly easier to implement. Cookies should always be very large random numbers that links to server side data. A cookie that contains a user id and time stamp doesn't help harden the session from attack.
This proposed session handler is more vulnerable to attack than using a Cryptographic nonce for each session. An attack scenario is as follows.
It is likely that you are using the same secret for your HMAC calculation for all sessions. Thus this secret could be brute forced by an attacker logging in with his own account. By looking at his session id he can obtain everything except for the secret. Then the attacker could brute force the secret until the hmac value can be reproduced. Using this secret he can rebuild a administrative cookie and change his user_id=1, which will probably grant him administrative access.
What makes you think this will improve performance vs. secure session IDs and retrieving the userid and time information from the server-side component of the session?
If something must be tamper-proof, don't put it in the toddlers' hands. As in, don't give it to the client at all, even with the tamper-proof locking.
Ignoring the ideological issues, this looks pretty decent. You don't have a nonce. You should add that. Just some random garbage that you store along with the userid and time, to prevent replay or prediction.

Resources