We are working on a GWT web-application which requires secure user authentication. We have the possibility of providing The credentials to the user via fax. So we can use pre-shared secret. There is no possibility for us to use ssl or https in this app.
I was wondering what will be the more secure way to store the pass on the server and authenticate the user; should we hash the password two times, I suspect?
If no encryption can be in place, you should hash the password on the client side (salted with a random salt provided by the server) and compare the resulting hash.
This approach has two advantages:
the hashed value is different each login
the password is never sent in plain text.
However, without encryption and proper authentication, session hijacking and such attacks are trivial.
Please note that there is no way to make this secure enough to foil any attack attempt of a reasonably competent malicious party without some sort of encryption/authentiaction layer on top of http, so it is probably for the best not to give the users any sense of false security, mmkay?
The biggest problem in the "let's only make the log-in as secure as possible" is that session side-jacking attack is rather trivial without encryption. Sidejacking (as defined in Wikipedia) is:
Session sidejacking, where the attacker uses packet sniffing to read network traffic between two parties to steal the session cookie. Many web sites use SSL encryption for login pages to prevent attackers from seeing the password, but do not use encryption for the rest of the site once authenticated. This allows attackers that can read the network traffic to intercept all the data that is submitted to the server or web pages viewed by the client. Since this data includes the session cookie, it allows him to impersonate the victim, even if the password itself is not compromised.[3] Unsecured Wi-Fi hotspots are particularly vulnerable, as anyone sharing the network will generally be able to read most of the web traffic between other nodes and the access point.
Related
JWT is used as user authentication in my project.
If someone intercepts packets(using wireshark, etc), takes the user's jwt token, and then tries to log request in using the jwt token(replay attack)
how can i defend using jwt? (my project is using https)
ps. English is not my native language, so I am not good at it, so please understand the awkward sentences.
A JWT literally IS your access token. So you have to keep it secure and especially transfer it securely by all means. If an attacker was able to obtain a JWT (for example by sniffing an unencrypted HTTP connection) he can always* use it to perform any action the user (respectively the token) is authorized to. So it's more of a use than a "replay attack".
Therefore you cannot directly defend using a JWT. You can only make sure to send it always over an encrypted HTTPS connection and to prevent Cross-Site-Scripting attacks, which could allow an attacker to steal the JWT.
* Because of this, a JWT generally has an expiration time. So if you keep the expiration time short an attacker could use the stolen JWT only in a small time period. However, also a small time period may be sufficient to achieve permanent access. And the attacker could possibly steal a fresh JWT via the initial source.
I was wondering if there is a more secure way of authenticating than forms authentication? I don't like the fact that when you login to a site using forms authentication, you can copy the cookie to another computer, and log in. I realise that if the site is browsed to over ssl there can be no man in the middle attack, however I still don't like the fact my site is vulnerable in this way.
Is there a good alternative available, other than windows authentication?
Thanks
You can look into token-based stuff, but what you will find is that there is always something that is stored on the client and passed for authentication instead of the actual user credentials (username and password). Whether it's a session id or a token does not really matter if you assume the attacker has the ability to access stuff on the client.
When token-based auth is used, the tokens are most of the times not kept in a cookie, but for example in browser memory (Javascript objects), or even worse, in places like localStorage. That is actually less secure than a good old session id in an httpOnly cookie, which is secure against cross-site scripting, as opposed to pretty much anything else in a browser.
So do realize that with almost any solution you choose, basically what happens is you exchange your user credentials for some kind of a token which you then use for authentication, and for the session the token is equivalent to your credentials, and there is not much difference between traditional sessions and tokens. Even Windows auth does about the same, but a layer below, on the OS level, which makes it less susceptible to attacks like XSS, but makes it vulnerable to attacks based on automatically sent session ids (like CSRF).
If you want to mitigate the threat of an attacker stealing session ids, you can for example design your application in a way that sessions are bound to client identifiers like the client ip address. That way even if a session id is stolen, the attacker still cannot use it. As another mitigation to that threat, you can prevent concurrent sessions, practically meaning logic around terminating all other sessions of a user that logs in. Note that these things are not specific to traditional sessions, the same applies to token-based auth, only the implementation is different.
Obviously, storing third-party credentials of any kind is a major risk, and I'd like to avoid it as much as possible. However, I have an idea as to how it could be relatively safe and I'd like some opinions on this strategy:
MySite allows users to register with a username and password (or Facebook, whatever)!
If that user is also registered at site AllTheData.com (herein called ATD) with a username and password, they can give me those over HTTPS.
MySite receives the third-party credentials to ATD and does two things: creates a new crypto-key which it stores in the user's cookies, AND encrypts the username and password with that key and stores those encrypted values in the database.
AllTheData.com's Database might look like this:
| User | Password
| JohnDoe#gmail.com | p4ssw0rd_hashed
MySite's database now looks like this:
| User | Password | ATD_username |ATD_pass
| JohnDoe#gmail.com | another_p4ssw0rd_hashed| ct5lHMGymedITfElVA...|BHJCS38DkG7Zg0...
And the user's browser has a cookie with the key:
MySite_key: E3iKZxk2ZDD4EUb*fH$X6Mz5BO^iQeOM&V$lB0WAk4&WAB#A4QB8Yn7
Now when I need to access the service I pull out the encrypted values from my database, and I pull out the cookie from their request, and I can access the server! And of course, if their cookie has expired or they've cleared them out or switched computers or anything else then I have to ask again : ( But it's worth it if it means I don't have to store credentials in plain!
Have I done anything terribly wrong here? Are there any obvious problems with this plan?
Thanks!
I agree with CBroe's comment. There are much better ways of interacting with a 3rd party than forcing your users to give up their precious credentials. I would suggest looking into something like OAuth. It allows your users a lot of great features:
They only present their ATD credentials to ATD
ATD can give them control over what data or actions your system can do for them. The user has the power to revoke your system's access at any time.
Most of the big third parties that you would want to integrate with are already OAuth providers
Since you've stated that OAuth is not an option, I would try one more plan of attack before using your proposed solution. You have already admitted that your solution is pretty transient; once a user clears their cookies, you require them to log in again. If the service that you are calling creates a session on login, you could simply forward the users credentials to the third party and temporarily cache whatever token or session ID the service would normally return to users (I see no reason to store this in a database). You could then delete that token once your user logs out of your system. This keeps you from storing their credentials directly. It's not a great step up, but that's what I would pursue first.
If you combine this with your cookie encryption idea, I think you get a pretty good separation. You have the encrypted authentication token cached on the server, but it is only accessible to users that have the encryption key stored as a cookie. Like you say, that prevents your server from giving access to the third party if you are compromised. You don't really get any protection if your client is compromised, but I think that's unavoidable.
If the system requires credentials for every request, then I don't really see a better approach. You've done your homework and I don't see any better solution.
This is not too bad, although not the best way of allowing access to a 3rd party system.
Make sure that the MySite_key is generated by a cryptographically secure algorithm so that it cannot be predicted by an attacker, and protect this cookie the best you can. If there is any breach on your site, the cookie becomes very valuable to an attacker. Of course, how valuable depends on what data the user has access to in ATD.
That means implementing SSL/TLS on your site, enforcing the Secure Flag and HTTP Only Flag on the cookie and setting a HSTS policy. Also ensure that your site does not have any session fixation vulnerabilities - if one existed an attacker may be able to set their own encryption key for another user's account.
Make sure the encryption algorithm is also secure enough for your needs, such as AES-128.
Also ensure that your communications with ATD are over SSL/TLS only. Again, using versions of the protocol and cipher suites that are considered secure and not vulnerable to any downgrade attacks (e.g. FREAK).
I've recently been reading on session cookies and how they can be hijacked via man-in-middle attacks. It seems this is mainly possible on an unencrypted connection between a client and a webserver.
However, I cannot figure out why, if one is already 'in the middle' of an unencrypted connection, would one prefer to capture the cookie instead of the username & password - a more valuable resource - which should also be sent in plaintext?
Stealing cookie is the easiest way to account hijacking.
unencrypted traffic does not mean that data is plain-text form. Especially mobile applications are using encryption methods on data before send it. For this reason, you will not be able to get username/password even if you doing MITM attacks.
You don't know clients are authenticated or not. Therefor when you start MITM attacks, you can't be sure all of your target are going to enter their username/password.
What about 2 factor authentication mechanism ? If you try to steal username/password rather than cookie value. How you planning to log-in 2 factor authentication enabled accounts ?
Let's assume I must store user's sensitive data, which was optionally encrypted on the client side.
Encryption (optional) should be done with user's passphrase.
User login (optional) should be done with user's password.
Notes:
A plain-text password is not stored on the server or transferred over the network.
My options and their drawbacks:
1. No authentication, Client-side authorization:
The server gives the data to everyone, but only the original user have the means to decode.
Data can be used by anyone to try to crack the encryption - not the best way to secure it.
2. Server-side authentication, no authorization:
Server stores user's password to access the data, and only gives the data to the user that can provide the right password.
Users don't trust the network for transferring their data without encryption.
3. Authentication and authorization:
Server stores user's password to access the encrypted data, the encryption is done using the passphrase that is different from user's password.
Good security, but users don't want to remember two passwords.
4. Authentication vs. Authorization:
Server stores user's password to access the encrypted data, the encryption is done using the same password.
Users are happy. Some security concerns.
I prefer the latest fourth option, but my concern is:
What if the server will get compromised, how can I be sure that encrypted password and encrypted data can't be used together to break the encryption?
How can I make it harder to break the encryption?
Some thoughts:
Use different encryption algorithms for password and data.
Add fixed string to the end of the user's password before encryption.
Pad user's password to some length.
EDIT:
The system should be very similar to a backup system that should be secure from all sides: the server should not be able to read the data, only the original client should be able to access the data and man in the middle attacks should be prevented. So if someone hacks the server authentication or the client encryption, the data should not be revealed.
It should be web based, so the man in the middle attack should be prevented with HTTPS.
To prevent server hacks revealing the data, the data is encrypted in client-side.
To prevent client encryption tampering, the access to the data should be protected on the server side with some log in and password or a token (may be unique URL).
#Vitaly, permit me to clarify some terms before I answer, as you seem to be using a different meaning for some than is commonly used.
Authentication - the process of proving who you are (more accurately, that you own the identity you are claiming).
Authorization - the mechanism used to restrict, control, and grant access.
Encryption - a mechanism for protecting data, even from someone who has access to it.
Now, allow me to rephrase your options, and then I'll suggest something else:
No Authentication, No Authorization, Client-side encryption
Server-side authentication, Server-side authorization, Server-side encryption
Server-side authentication, Server-side authorization, Client-side encryption
Server-side authentication, Server-side authorization, Client-side encryption using server credentials.
Now, I think it can be clearer where each one stands.
In general, you really want to follow the "best practice" (dont get me started on those) principle of "Defense in depth", i.e. dont use only encryption, or only access control, instead use both! But, as you pointed out, this can be in contrast (if the user is required to remember TWO passwords) to another principle, "Keep Security Simple".
Without trying to be TOO annoying, you didn't give much information in the way of your environment. For example, is this e.g. a Web application? If so, why is SSL/TLS not enough encryption for you? Or is this a question of users uploading personal data that you (and your system) should not see either (e.g. a backup-type service)? In which case client-side encryption would be necessary...
So, (finally) my proposed options, depending on your environment / requirements:
If you can, rely on secure protocols (e.g. SSL/TLS) for encryption. Use server-side authentication + authorization, protocol encryption.
If your system needs to further protect this data, e.g. credit cards (note that I am not currently a PCI:QSA ;) ), use the previous option, and in addition server-side encryption using a server-generated encryption key (NOT the password) (and of course protect that).
If the data needs to be protected FROM your system, you will need to do client-side encryption IN ADDITION to server-side authentication+authorization (your option 3 as I restated it).
However, you don't necessarily need to force the user to remember an additional password/phrase. Again, depending on your environment, you might be able to consider some form of key stored on the client, e.g. a certificate in the user's certificate store / keyring, or even stored in a protected configuration file; a key based on biometric data (not easy but i've seen this done successfully, though it has its own set of issues), out of band key distribution (e.g. via cellphone), etc. This would enable you both to use strong keys, prevent the server from accessing those keys, not require the user to remember two keys, and doesn't re-use a single password for different usages in different contexts.
You could take a look at zero-knowledge protocols for authentication, in particular to the Secure Remote Password protocol, which makes it possible to perform password-based authentication without revealing the password to the server. This way the same password can be used both for authentication and for deriving a data encryption key.
Also, you could take a look at the Clipperz online service, which implements something similar to your needs and is also open source.
Use option one and make the URL for the data contain a long random string. Anybody who knows the random string can get the data. Of course, only the client who created the data is going to have that URL right off.
If someone wants to give someone else revokable access, allow them to generate a new random URL and provide a means for them to name that random URL and revoke its ability to get at the data.
Capability based security is easier to get right, more flexible and makes more sense to users. There is a really excellent YouTube video about capability based security and a nice website with some essays about it.