TOTP : Changing secret upon every session - security

I have such requirement about changing the users secret for every session for generating OTP. We decided to use TOTP as our algorithm to do so. We are sending OTP in SMS to the user for authorization verification (no need to generate OTP at client side).
TOTP = HOTP(WhereSessionCalculate(SecretKey), TC)
So, Is it good practice to change the secret of an user session wise. If not then what are the consequence that can possibly arise. Please explain and let me know if more information needed.

The basic premise of two-factor (or multi-factor, to be more accurate) authentication is to supplement the normal username/password combination - these are things you know - with one or more additional factors of a different type. Most commonly used are what you have (e.g. your cellphone, with a Google Authenticator app or an RSA, Gemalto etc. token) or something about what you are (biometric data such as iris, fingerprint etc.)
Someone can learn a username and password from shoulder-surfing (easy if the password is short), even sniff it from an insecure network connection (hope you're using SSL with AES256 or somesuch to encrypt the sessions to your app!) but the addition of 2FA stops that.
So let me some back to your question and whether your approach is accretive to the security of authenticating your users . Once the user's OTP key is set and stored in the user's record in the database, and that key is used to seed the TOTP generator, what would having the user re-seed with a new key accomplish? Yes, generating a OTP code and sending by SMS verifies that the person logging on has their phone with them at that very moment, but then so would using Google Authenticator; moreover, and I betray my Apple fanboi bias here (!) incoming SMSes are displayed on the lock screen of my iPhone, which would also therefore display your OTP, whereas to access the Google Authenticator app I have to unlock my phone with my PIN.
Also bear in mind that most systems are compromised at a network or system level and whole databases of usernames and passwords stolen to be cracked - compromising a single user's access isn't generally worth the trouble, unless you have a very high value asset attracting the attention of state actors!
Having explored the issues here for my own app I've gone with a username and password initial login (minimum length 20 characters to perplex rainbow tables, but with no stipulation on complexity or frequent changing), maximum number of attempts before locking the account for an increasing amount of time for failed logins, and a secondary login using Google Authenticator (as it's free, runs on iOS, Android and BB10, and is pretty easy to use). To improve on this I would consider biometrics but my application is commercial not military etc. so what I have is quite enough for my assessment of the risk.
I hope that helps you work out the best approach for your application.

Related

Is it secure if I store a sha1 password and a userID in secure flag & https Cookies?

I'm doing a connection system for my users. So I decided to use Cookies to store the User ID and the password (in sha1). But I have one question. If a random user gets the value of both cookies and their names, can he creates them with for example a js function and get into the account?
Is it secure if I store a sha1 password and a userID in secure flag &
https Cookies?
No.
I suppose you want to know why? First, define "safe." What threat are you trying to mitigate?
Once the credentials are hashed, there's no way to get the plaintext back. Since you can't render the hashed string back to plaintext then we can assume that the intent is to compare them to the same hashed string held at the server, yes? That's awesome if the threat you want to mitigate is somebody discovering the password and user ID and you use something like SHA256 instead of SHA1.
But if the threats you want to mitigate include replay attack or session hijacking, then these are no better than any other fixed string. In fact they are worse. If the user is obliged to provide their password for each HTTPS request it sucks for them but at least the app can throttle login attempts and foil a brute force attack. If the credentials are hashed and exchanged in cookies, then they are exposed to adversaries and if obtained can be subjected to brute force cracking or looked up in a rainbow table so on net sending the credentials back out, even encrypted or hashed, kinda sucks.
The question doesn't mention salt or session keying. An adversary will look at the cookies to see identical values are returned over multiple sessions. To prevent replay attack you'd need to append a nonce before hashing to act as a salt so the hashed string changes each time. But it doesn't solve the problem of sending a transformed credential pair outside of control of your own server or that this is far worse than just using a long random string for the same purpose.
Furthermore, the hash of the credentials doesn't time out until and unless the user changes their password - at which point it tells an adversary that the user just changed their password which is a great piece of info with which to social engineer the IT support person who does password recovery. "Hi, I just changed my password and locked the account. Can you reset it? Employee ID? Well if I had access I could look it up. Can you just reset it? I'm really me. How else would anyone I know I just changed it?"
The support person would never guess the answer to that question is "because Victor's app design told me it was just changed" and might just reset it for the adversary. But if the session is kept alive by a session cookie or a triparte login token then the unique string representing that user's session mitigates all of the threats discussed so far:
An attacker can't reverse it or crack it to discover credentials because they aren't in there.
It can't be used for session replay since it is generated to be unique for each session.
It expires within a short period of time so it can't be resurrected from browser cache or history.
But rather than answer the question as asked, I'd like to answer the question "Is there an authoritative source for comprehensive web application security best practices?" That's a much easier question to answer and it potentially answers your initial question if you follow through with the required study.
Please see: Open Web Application Security Project (OWASP).
In particular, please see the Session Management Cheat Sheet and the Authentication Management Cheat Sheet as these cover much of what you are trying to do here.
OWASP periodically analyzes all reported breaches for a recent period and then publishes the Top 10 Vulnerability List based on the root causes that showed up most often during the sample period. When I QA new web sites on behalf of clients they almost always have several of the defects in OWASP's Top 10 list. If as a developer or web site development company you want to stand head and shoulders above the crowd and get a lot of repeat business, all you need to do is make sure the site you deliver doesn't have any defects in OWASP's list. The question suggests any application built as proposed would have at least 4 or 5 defects from the OWASP Top 10 so that's an aspirational goal for now. Aim high.

Two - Step authentication, how does it work?

So as part of a project, I want to implement a two step authentication system (in rails)
I understand the principles of it,
=> Client: Username and password
<= Server: Generate PIN code and send it to client via SMS/email
=> Client: enter PIN
<= Server: authenticate client as normal
Now what I want to know is in a web based application such as rails, the PIN needs to be kept secret at every point, so when redirecting from the username/password part to the PIN part, I need to keep the PIN code secret while passing it over to the next part of the system (the PIN part)
Is the only decent way to do this, by temporarily storing the PIN in the database alongside a user ID?
No, not quite that.
There are two (most used) types of one-time passwords (OTPs, PINs in your terminology):
Time-based
Counter-based
Time-based ones (TOTP) generate some number based on current time (for example: number of 30-second intervals from 1970.1.1 00:00) and some shared secret. When receiving such one-time password, server generates one on its side and checks whether it's correct.
In counter-based OTPs, you have a counter and a secret key stored in database near user ID, and it is used to generate the OTP. It can be incremented based on login attempt.
Time-based tokens are usually better, as they don't require counter synchronization (time synchronization is usually easier). Best example of this is the Google Authenticator, which implements standard TOTP from RFC6238.
There's one Ruby OTP library which claims compatibility with Google Authenicator, you may want to try it out: link
Can't vouch for its security and/or quality, but it looks promising.

Sending username and password as md5 hash for every request from iPhone game

I am building a simple iPhone game which has a community maps feature.
Users sign up for an account with just their email and password, and then they can build, upload and download custom maps.
Now I know that sending the username and password with every request is usually a bad idea, but it is a lot easier for development instead of having to deal with login session, and I think it is okay for situations where security isn't a major concern.
The most important thing is to protect the user's password as they likely use the same password for multiple accounts.
So the simple approach I think is this: Send the user's username and password as one md5 hash with every request. Would this be okay?
Sure there is a risk someone might hijack the request, but login sessions have the same risk. And if a hacker got hold of a user's login session, don't they just need to force that user to log off so the client will send the user's username and password in the next request?
I haven't got any experience with mobile app development, however some general principles still apply. Firstly MD5 is flawed, don't use it. And if you are going to use a different algo (depends on your choice, and what what security/speed you are looking for, for thing like that I'd probably go for blowfish, but SHA512 should also do the job), definitely use salts.
I still think though that a simple session management would be better than sending the login information with every request, simple random session id should do (you generate it upon log in and associate with a particular user); of course there you run in a trouble with randomness of the ids (if they are predictable it is obviously a problem).
But I suppose the major point here is how will the app communicate with the server; if it is encrypted (HTTPS I would presume) you should be fine either way, I think is more important than whether you use sessions or hashed login info. And usage of HTTPS should take care of your worries about request/session hijacking as well (unless someone cracks the encryption with 200 modified PS3 units :) )

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

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.)

How can you encrypt users' data server-side without ruining the experience?

Many users – myself included – would like the security of having everything they do on a web service encrypted. That is, they don't won't any one at the web service to be able to look at their: posts, info, tasks, etc...
This is also major complaint in this discussion of an otherwise cool service: http://news.ycombinator.com/item?id=1549115
Since this data needs to be recoverable, some sort of two-way encryption is required. But unless you're prompting the user for the encryption key on every request, this key will need to be stored on the server, and the point of encrypting the data is basically lost.
What is a way to securely encrypt user data without degrading the user experience (asking for some key on every request)?
-- UPDATE --
From #Borealid's answer, I've focused on two possibilities: challenge-response protocols, where no data (password included) is sent in the "clear", and non-challenge-response protocols, where data (password included) is sent in the "clear" (although over HTTPS).
Challenge-response protocols (specifically SRP: http://srp.stanford.edu/)
It seems that its implementation would need to rely on either a fully AJAX site or using web storage. This is so the browser can persist the challenge-response data during encryption and also the encryption key between different "pages". (I'm assuming after authentication is completed I would send them back the encrypted encryption key, which they would decrypt client-side to obtain the real encryption key.)
The problem is that I'm either:
fully AJAX, which I don't like because I love urls and don't won't a user to live exclusively on a single url, or
I have to store data encryption keys in web storage, which based on http://dev.w3.org/html5/webstorage/ will persist even after the browser is closed and could be a security vulnerability
In addition, as SRP takes more than one request ( http://srp.stanford.edu/design.html ), there needs to be some persistence on the server-side. This is just another difficulty.
Traditionally
If I'm ok transmitting passwords and data in the clear (although over HTTPS), then the client-side issues above are not present.
On registration, I'll generate a random unique encryption key for the user, and encrypt it using their password and a random salt.
In the database, I'll store the user's password hash and salt (through bcrypt), encrypted encryption key, encryption key salt, and encryption iv.
After an authentication, I'll also need to use their password to decrypt the encryption key so that they may view and enter new data. I store this encryption key only temporarily and delete it when they explicitly "log out".
The problems with this approach is that (like #Borealid points out) evil sysadmins can still look at your data when you are logged in.
I'm also not sure how to store the encryption keys when users are logged in. If they are in the same data store, a stolen database would reveal all data of those who were logged in at the time of theft.
Is there a better in-memory data store for storing these encryption keys (and challenge data during an SRP authentication)? Is this something Redis would be good for?
If the data need to be recoverable in the event of user error, you can't use something like a cookie (which could get deleted). And as you point out, server-side keys don't actually secure the user against malicious sysadmins; they only help with things like databases stolen offline.
However, if you're running a normal web service, you've already gotten pretty lucky - the user, in order to be unique and non-ephemeral, must be logged in. This means they go through some authentication step which proves their identity. In order to prove their identity, most web sites use a passed credential (a password).
So long as you don't use a challenge-response authentication protocol, which most web sites don't, you can use an encryption key derived from a combination of a server-side secret and the user's password. Store the encryption key only while the user is authenticated.
If you do this, the users are still vulnerable to sysadmins peeking while they're using the service (or stealing their passwords). You might want to go a step further. To go one up, don't send the password to the server at all. Instead, use a challenge-response protocol for authentication to your website, and encrypt the data with a derivative of the user's password via JavaScript before uploading anything.
This is foolproof security: if you try to steal the user's password, the user can see what you're doing because the code for the theft is right there in the page you sent them. Your web service never touches their data unencrypted. This is also no hindrance to the normal user experience. The user just enters their password to log in, as per normal.
This method is what is used by Lacie's storage cloud service. It's very well done.
Note: when I say "use foo to encrypt", I really mean "use foo to encrypt a secure symmetric key which is then used with a random salt to encrypt". Know your cryptography. I'm only talking about the secret, not the methodology.
None of those other solutions are going to maintain the feature set requested -- which specifically wants to preserve the user experience. If you look at the site referenced in the link, they email you a nightly past journal entry. You're not going to get that with JavaScript trickery per above because you don't have the browser to depend on. So basically this is all leading you down a path to a degraded user experience.
What you would want, or more precisely the best solution you're going to find in this space, is not so much what wuala does per above, but rather something like hush.com. The handling of user data needs to be done on the client side at all times -- this is generally accomplished via full client-side Java (like the Facebook photo uploader, etc), but HTML/JavaScript might get you there these days. JavaScript encryption is pretty poor, so you may be better off ignoring it.
OK, so now you've got client-side Java running a Journal entry encryption service. The next feature was to email past journal entries to users every night. Well, you're not going to get that in an unencrypted email obviously. This is where you're going to need to change the user experience one way or the other. The simplest solution is not to email the entry and instead to provide for instance a journal entry browser in the Java app that reminds them of some old entry once they get to the website based on a link in the daily email. A much more complex solution would be to use JavaScript encryption to decrypt the entry as an attachment inline in the email. This isn't rocket science but there is a fairly huge amount of trickery involved. This is the general path used by several web email encryption services such as IronPort. You can get a demo email by going to http://www.ironport.com/securedemo/.
As much as I'd love to see a properly encrypted version of all this, my final comment would be that journal entries are not state secrets. Given a solid privacy policy and good site security semantics, I'm sure 99% of your users will feel just fine about things. Doing all this right with true security will take an enormous amount of effort per above and at least some design/UE changes.
You should look into the MIT project CryptDB which supports querying an encrypted database using a subset of SQL. (see the forbes article, mefi thread, or Homomorphic encryption on wikipedia)
There is the Tahoe-LAFS project for cloud storage too, which conceivably could be leveraged into a fully anonymous social networking application, one day in the distant future.
If you want to perform computations on a server without even the server being able to see the data, you may be interested in knowing about fully homomorphic encryption. A fully homomorphic encryption scheme lets you perform arbitrary computations on encrypted data, even if you can't decrypt it. However, this is still a topic of research.
For now, I guess your best bet would be to encrypt all posts and assign meaningless (e.g. sequential) IDs to each one. For a more in-depth discussion of how to encrypt server-side data with today's technology, look up.

Resources