Should user data be encrypted on the client or server side? - security

I have a small question to ask you! When a user registers on a site, his password is stored, encrypted, in the database. Encryption is possible in PHP thanks to different functions, notably password_encrypt from memory. In this case, the encryption operates on the server side.
BUT
we can imagine that we encrypt the password in JavaScript, so on the client side, and that we send to the server the already encrypted password!
My question is the following: when the encryption is done on the server side, is there any way to intercept the unencrypted password ON THE SERVER, just before it is encrypted (spy scripts, etc.). In this case, perhaps client-side encryption should be preferred, so if the server is controlled by an attacker, it does not compromise user security.
Also, for the user's trust, isn't client-side encryption better?
What about known sites? Do they encrypt data on the server or client side?
Thank you in advance!

Related

I STILL think hashing password on client side is better. Am I wrong?

I've read these:
https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5
https://security.stackexchange.com/questions/8596/https-security-should-password-be-hashed-server-side-or-client-side
Is it worth hashing passwords on the client side
Password encryption at client side
https://softwareengineering.stackexchange.com/questions/76939/why-almost-no-webpages-hash-passwords-in-the-client-before-submitting-and-hashi
... and I STILL think that hashing your password on the client side is better. Let me explain.
The first cited article advocates that you should make the login page stand alone since there's no way to trust the entire codebase used in the client side. I think it makes sense.
And if it makes sense, how can you trust the entire codebase used in the server side?
So many upvoted answers above are claiming that "don't hash on client side, because TLS exists". That's true for preventing the password from sniffed, but is not related at all if it's about our potentially-evil server side code.
Also, I don't see any reason for the server side to hash the password if it's hashed already. If your server is cracked, you're done - regardless of the passwords - but the cracker can't use the obtained passwords anywhere else.
But since I can find no such answer, my statement seems to be fundamentally wrong. What am I missing?
If you think hashing BOTH client AND server side with a modern password hashing algorithm like PBKDF2, BCrypt, SCrypt, or Argon2 with a high work factor/iteration count is better, then I agree.
If you think hashing ONLY client side is better, then I have serious reservations about your threat model.
There are threats that hashing passwords server-side protects against, and threats that client-side protects against; here's a brief list:
BOTH: leaked password database entries allowing viewers to see what the user typed in cleartext.
CLIENT: Server-side insiders with packet/traffic interception access seeing what the user typed in directly
This is one of the two major threats that client side hashing IN ADDITION to server side hashing is a good fit for mitigating.
SERVER: Insiders with database access fradulently impersonating actual users
if passwords are ONLY hashed client side, then whatever's in the server DB can be fed to the system via the client request to log in as the user "legitimately" according to the server. This makes all server audit logs of who did what suspect.
if passwords are hashed server side, regardless of what happened client side, what is in the server does NOT authenticate the user if fed in via the normal authentication channel.
CLIENT: MitM attacks seeing what the user actually typed in
This is the other major threats that client side hashing IN ADDITION to server side hashing is a good fit for mitigating.
MitM attacks can come from the client's corporate IT department, a network provider or other ISP, the server organization's IT department (load balancers or advanced security appliances with the actual cert key, etc.), or many other sources.
NEITHER: MitM attackers fradulently impersonating actual users
No matter whether you hash it client side or not, what gets sent over the network to the server app IS what the server uses to authenticate you.

What is a good browser level encryption product?

I'm looking for a product that can provide browser-level encryption of textual data before it's sent to a backend server. HTTPS can be the secure transport mechanism but we need the packet to be encrypted on the browser first. The data packet must end up in encrypted form on the backend database. Use case is: user fills out form on the browser, user submits the form data, before sending the data over the wire, the browser encrypts the data, the data ends up in the backend database in encrypted form, at some point in time, all of the data will be collected from the backend database, moved to a disconnected computer and decrypted at that point.
HTTP over SSL/TLS (HTTPS) is secure enough. It actually is as secure as it gets.
With SSL/TLS you can choose the cipher suite and adjust the encryption algorithms and key sizes according to your needs. 2048-bit RSA and 256-bit AES should be secure enough.
In addition to encryption, SSL provides authentication. AND it is natively supported by virtually every browser in existence. Please don't reinvent the wheel.
I agree that TLS is good enough for a lot of cases and I've written a little about it in my journey to see how it works. It does have some issues like governments being able to compel certificate authorities to grant certificates to allow man-in-the-middle attacks, but in general it's pretty good.
You might be interested in the design of systems like LastPass that encrypt things in addition to using TLS (details here). I would say that your best approach if you think TLS isn't good enough is to do something in addition to it rather than in lieu of it.
That's what HTTPS (SSL/TLS) is for. It should be plenty secure enough.
But as you state in your answer to my query, you want the form data to be stored in the database in its encrypted form. A quick Google search brings up JQuery.Gibberish-AES. It's a JQuery plugin that will do AES encryption and can utilise an RSA public key.
Using this you could generate a public/private key pair, keep the private key on the super-secret disconnected computer, and publish the public key with your form. You can then encrypt the data, store it in your database, and even if someone got root access to the database server they could decrypt the data because the secret key is on your secure disconnected machine.
I'm sure there'd be similar plug-ins/libraries for other client-side frameworks if you don't use JQuery.
I'd still use SSL/TLS for the connection, because that provides the server authentication (and client authentication if you want) to protect against a man-in-the-middle.

How can I improve my client-server system's security?

I've built a client-server system, where clients sign in to communicate securely with other clients through the server.
Here are the properties of my system:
-Client-server communication is SSL encrypted
-Client login details are stored as hashes securely with their salt on a database stored locally on the server
-On login, every client sends a session public key to be stored on the server, which other clients use to encrypt a symmetric key. The symmetric key is used for later message encryption to prevent server eavesdropping
-On chat initiation, fingerprint user authentication is used to ensure user is who he/she pretends to be. It is usually done through a phone call reading out the fingerprint, which is a SHA256 hash of both public keys split in two and XORed for convenience.
-MAC is sent along with every message
What would you suggest to improve this? What possible attacks could my server suffer?
Thanks
It seems like you could still suffer from a Trojan client application, but what you really need to do is take a step back from the various security technologies. What does all this security protect? Who would like to break it? What would they do if they could break it? Answers to those questions will help you identify how the system might be attacked, and propose useful countermeasures.
It looks like you are looking at this problem haphazardly - build a threat model of your design; and mitigations will come to you! Start here: http://www.microsoft.com/security/sdl/getstarted/threatmodeling.aspx

Password hashing at client browser

What's the best way to hash the user password at the client browser, before sending it to the web server, so that only the hash goes out, not the plain-text password?
EDIT: assuming HTTP is used (not HTTPS)
Use javascript to calculate the hash. See this for an example on how to calculate SHA-1 hashes in JS.
Beware that if you make yourself dependant on Javascript, your system will fail as soon as someone has JS disabled. You should use HTTPS if this is a concern to you, which has its own setbacks (e.g. certificates cost money if you want them to be immediately accepted by browsers.)
Try using this jQuery encryption plugin. Out of curiosity, what's wrong with using SSL/HTTPS and encrypting at the server side?
Not all people have JavaScript enabled in their browsers and even the idea of sending hashes on a plain-text channel I think is not secure enough.
I would recommend you to consider a SSL secured connection.
This site has quite comprehensive hashing/crypto stuff: JavaScript Encryption Library
JavaScript side encryption like the jQuery Encryption library stops Eavesdroppers. However, MITM (Man-in-the-Middle) can still occur. SSL/TLS is the ultimate choice that is highly recommended to take unless you are on shared hosting (no dedicated IPs) or your site is receiving so much traffic that you can't simply encrypt all connections (JS, CSS, HTML, ...).
Why would you bother doing this? Effectively, the password hash has become the password and a a man-in-the-middle who intercepts the hash can use it to authenticate and perform any action as the user. On the other hand, if you don't believe in the man-in-the-middle, why not just send the password itself?
Why do we hash passwords? So that if the hashes are obtained they're difficult to use.
What happens in this model if the hashes in the system are exposed? The attacker simply sends them to the server and authenticates as the user.
This is why password hashing always happens on the server, not the client!

Website login: how should user credentials be sent to the server for verification?

I'm working on a project in which remote clients need to log in to a webserver. I'm not looking for examples in any particular language; just a general idea of the security concerns involved.
The basic question is:
How should user credentials be passed to a webserver for verification?
I'm picturing your typical website login. One field for username, and another for password. You type in both and click "Log In". What happens next?
I can imagine a few scenarios:
Credentials are sent to the server as plain text. A server-side script creates a hash of the password and compares it to the stored hash for the user.
Credentials are encrypted locally, and the result is sent to the server. The server decrypts the credentials and continues as in #1
Something I haven't thought of yet? I'm new to this. Go easy on me!
Option #1 strikes me as weak because the credentials are sent over the internet in plain text.
I see option #2 as not much better than option #1. If someone intercepts the encrypted credentials, can they not just send those to the server another time, and still manage to log in?
Any insight is appreciated.
edit: the "Related" sidebar suggests this question, which mentions a client/server handshake with a salt added to the password. Is that the right way to go?
Option 1 is by far the default. The plaintext weakness is usually overcome by enforcing SSL during the login so that the password is at least encrypted during transit.
Edit: I suggest you follow the accepted answer for that question.
Don't forget to require a nonce for your request. This will help protect you against replay attacks.
Edit the second: Wayne thoughtfully mentioned that you should salt your password before you hash. Here are some basic tips:
It doesn't matter if your salt is a prefix, postfix, or infix
Your salt should be large, random, and complex.
Your salt should be unique per salted value. The salt itself doesn't need to be encrypted.
Why not SSL the communications? Being able to observe the conversation gives me insight into your app. Encrypt the entire communication, not just the credentials.
Edit: Always use salt for a locally stored hash. Windows continues to fail as far as brute forcing locally hashed passwords because they do not salt by default.
The simplest answer is to get an SSL certificate for your server. There's really no reason to mess around with creating your own encryption techniques in this particular application. As you've noted, if the connection isn't encrypted, you leave yourself open to man-in-the-middle attacks, regardless of whether the client or the server is doing the password encryption. Encrypt the connection, and you don't have to worry about it.
On the client side you only have a browser that can render HTML and submit forms. Who's gonna encrypt stuff?
Send login and password in plain text (SSL it if you have concerns). On the server side you can do whatever you want with it (preferrably hash and salt password before storing them in the database).
You might also want to consider using multiple iterations of the hash algorithm, 1000 iterations will slow things down nicely and make rainbow tables that much harder to create

Resources