Why doesn't OWASP recommend to bcrypt the password both on the client and the server?

后端 未结 4 1476
醉酒成梦
醉酒成梦 2021-01-18 18:01

Since the recent problems with GitHub and Twitter:

  • GitHub Accidentally Recorded Some Plaintext Passwords in Its Internal Logs
  • Twitter Admits Recording
4条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-18 18:51

    I was looking to resolve a similar issue where plain-text password can be logged on the server. The conclusion is that you should always additionally hash the client password if able.

    Here is some articles about client-plus-server hashing:

    Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server

    Salted Password Hashing - Doing it Right

    Specifically, see:

    In a Web Application, always hash on the server

    If you are writing a web application, you might wonder where to hash. Should the password be hashed in the user's browser with JavaScript, or should it be sent to the server "in the clear" and hashed there?

    Even if you are hashing the user's passwords in JavaScript, you still have to hash the hashes on the server. Consider a website that hashes users' passwords in the user's browser without hashing the hashes on the server. To authenticate a user, this website will accept a hash from the browser and check if that hash exactly matches the one in the database. This seems more secure than just hashing on the server, since the users' passwords are never sent to the server, but it's not.

    The problem is that the client-side hash logically becomes the user's password. All the user needs to do to authenticate is tell the server the hash of their password. If a bad guy got a user's hash they could use it to authenticate to the server, without knowing the user's password! So, if the bad guy somehow steals the database of hashes from this hypothetical website, they'll have immediate access to everyone's accounts without having to guess any passwords.

    This isn't to say that you shouldn't hash in the browser, but if you do, you absolutely have to hash on the server too. Hashing in the browser is certainly a good idea, but consider the following points for your implementation:

    Client-side password hashing is not a substitute for HTTPS (SSL/TLS). If the connection between the browser and the server is insecure, a man-in-the-middle can modify the JavaScript code as it is downloaded to remove the hashing functionality and get the user's password.

    Some web browsers don't support JavaScript, and some users disable JavaScript in their browser. So for maximum compatibility, your app should detect whether or not the browser supports JavaScript and emulate the client-side hash on the server if it doesn't.

    You need to salt the client-side hashes too. The obvious solution is to make the client-side script ask the server for the user's salt. Don't do that, because it lets the bad guys check if a username is valid without knowing the password. Since you're hashing and salting (with a good salt) on the server too, it's OK to use the username (or email) concatenated with a site-specific string (e.g. domain name) as the client-side salt.

    After researching, it seems that there is a clear security benefit in hashing the client as well. If the password over HTTPS is compromised or if the password is logged on the server, then the plain-text password could not be easily reused on the user's other accounts (many users reuse their passwords).

    The only possible downside is client performance, and server-side password validation. A user can manipulate your client JS and submit a "weak" password. The server wouldn't know any better. But I think this is a small issue, and it relies on people intentionally modifying their client code in order to weaken their own security.

提交回复
热议问题