CouchDB
  1. CouchDB
  2. COUCHDB-1060

CouchDB should use a secure password hash method instead of the current one

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 1.0.2
    • Fix Version/s: 1.3
    • Component/s: Database Core
    • Labels:
      None

      Description

      CouchDB passwords are stored in a salted, hashed format of a 128-bit salt combined with the password under SHA-1. This method thwarts rainbow table attacks, but is utterly ineffective against any dictionary attacks as computing SHA-1 is very fast indeed.

      If passwords are to be stored in a non-plaintext equivalent format, the hash function needs to be a "slow" hash function. Suitable candidates for this could be bcrypt, scrypt and PBKDF2. Of the choices, only PBKDF2 is really widely used, standardized and goverment approved. (Note: don't be fooled that the PBKDF2 is a "key derivation" function - in this case, it is exactly the same thing as a slow password hash.)

      http://en.wikipedia.org/wiki/PBKDF2

      1. pbkdf2.erl
        3 kB
        Robert Newson
      2. pbkdf2.erl
        4 kB
        Robert Newson
      3. 0001-Integrate-PBKDF2.patch
        21 kB
        Robert Newson

        Activity

        Robert Newson made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Jan Lehnardt made changes -
        Fix Version/s 1.3 [ 12318350 ]
        Fix Version/s 1.2 [ 12315198 ]
        Hide
        Jan Lehnardt added a comment -

        Bump to 1.3.x.

        Show
        Jan Lehnardt added a comment - Bump to 1.3.x.
        Robert Newson made changes -
        Attachment 0001-Integrate-PBKDF2.patch [ 12492631 ]
        Hide
        Robert Newson added a comment -

        Integrate PBKDF2 as new default password hash algo.

        Auto-updates validate_doc_update for users to include rules on new scheme.

        couch.js's prepareUserDoc updated to create new scheme

        Show
        Robert Newson added a comment - Integrate PBKDF2 as new default password hash algo. Auto-updates validate_doc_update for users to include rules on new scheme. couch.js's prepareUserDoc updated to create new scheme
        Hide
        Chris Anderson added a comment -

        The current implementation avoids a special server side API for creating documents in the _users database. Architecturally, I am fine with a special API for the user's database – however it may make sense to keep it in the "shape" of the CouchDB API. So for instance creating a user would go through an _update function, which could compute the salt and hash, before storing in the _users db.

        The alternative would be to define a custom endpoint for POST requests to create documents in the user db, and then we'd have to bike-shed and document that API.

        However if someone wants to write all that code, I won't stop you. If energy is going to poured in here, the other thing we should consider is a "write-only" database mode, so that users can PUT and POST, but not GET. In this case the _update function would still be a good way to do the salt and hashing. Anyway, this is a distinct topic but related.

        Show
        Chris Anderson added a comment - The current implementation avoids a special server side API for creating documents in the _users database. Architecturally, I am fine with a special API for the user's database – however it may make sense to keep it in the "shape" of the CouchDB API. So for instance creating a user would go through an _update function, which could compute the salt and hash, before storing in the _users db. The alternative would be to define a custom endpoint for POST requests to create documents in the user db, and then we'd have to bike-shed and document that API. However if someone wants to write all that code, I won't stop you. If energy is going to poured in here, the other thing we should consider is a "write-only" database mode, so that users can PUT and POST, but not GET. In this case the _update function would still be a good way to do the salt and hashing. Anyway, this is a distinct topic but related.
        Hide
        Robert Newson added a comment -

        Filipe,

        It might be fine, but I think it misses the point. It's weird to create the value on the client side anyway. We should pass the password as entered, and let the backend salt it and digest it. The transmission should be protected by SSL, which we can do from 1.1 onwards.

        Show
        Robert Newson added a comment - Filipe, It might be fine, but I think it misses the point. It's weird to create the value on the client side anyway. We should pass the password as entered, and let the backend salt it and digest it. The transmission should be protected by SSL, which we can do from 1.1 onwards.
        Hide
        Filipe Manana added a comment -

        Robert, https://github.com/bitwiseshiftleft/sjcl

        I have no idea however if this implementation is too slow or acceptable.

        Show
        Filipe Manana added a comment - Robert, https://github.com/bitwiseshiftleft/sjcl I have no idea however if this implementation is too slow or acceptable.
        Hide
        Robert Newson added a comment -

        I think Chris means the use of sha1 in jquery.couch.js or thereabouts. Calculating a pbkdf2 value in javascript being a bit tricky.

        Show
        Robert Newson added a comment - I think Chris means the use of sha1 in jquery.couch.js or thereabouts. Calculating a pbkdf2 value in javascript being a bit tricky.
        Hide
        Paul Joseph Davis added a comment -

        What server?

        Show
        Paul Joseph Davis added a comment - What server?
        Hide
        Chris Anderson added a comment -

        I love this. Currently the user passwords are too insecure. A slow hash algorithm makes offline cracking harder.

        It would require changes to the API to have crypto only run on the server, but it might be simpler.

        Chris

        Show
        Chris Anderson added a comment - I love this. Currently the user passwords are too insecure. A slow hash algorithm makes offline cracking harder. It would require changes to the API to have crypto only run on the server, but it might be simpler. Chris
        Robert Newson made changes -
        Fix Version/s 1.2 [ 12315198 ]
        Robert Newson made changes -
        Assignee Robert Newson [ rnewson ]
        Robert Newson made changes -
        Attachment pbkdf2.erl [ 12474380 ]
        Hide
        Robert Newson added a comment -

        Fully compliant pbkdk2 module, all test vectors pass.

        Show
        Robert Newson added a comment - Fully compliant pbkdk2 module, all test vectors pass.
        Robert Newson made changes -
        Field Original Value New Value
        Attachment pbkdf2.erl [ 12474359 ]
        Hide
        Robert Newson added a comment -

        Incomplete implementation of pbkdf2.

        First two test vectors pass so it's not complete crap.

        Show
        Robert Newson added a comment - Incomplete implementation of pbkdf2. First two test vectors pass so it's not complete crap.
        Hide
        Paul Joseph Davis added a comment -

        And I'd put my hat in the ring for UYIT896HL hashing. Its my fav.

        Show
        Paul Joseph Davis added a comment - And I'd put my hat in the ring for UYIT896HL hashing. Its my fav.
        Hide
        Robert Newson added a comment -

        If we're doing this, I'd much rather see PBKDF2 than bcrypt.

        Show
        Robert Newson added a comment - If we're doing this, I'd much rather see PBKDF2 than bcrypt.
        Hide
        Paul Joseph Davis added a comment -

        Hrm, four clause BSD though. Do we do that?

        Also, there's this:

        http://bcrypt.sourceforge.net/

        Which is three clause. Hooking it up to a NIF or port driver wouldn't be overly difficult.

        Show
        Paul Joseph Davis added a comment - Hrm, four clause BSD though. Do we do that? Also, there's this: http://bcrypt.sourceforge.net/ Which is three clause. Hooking it up to a NIF or port driver wouldn't be overly difficult.
        Hide
        Randall Leeds added a comment -
        Show
        Randall Leeds added a comment - Whoops. Link: https://github.com/skarab/erlang-bcrypt
        Hide
        Randall Leeds added a comment -

        There is an erlang-bcrypt project on github. Looks like MIT-like and BSD licensing on all the components.

        Show
        Randall Leeds added a comment - There is an erlang-bcrypt project on github. Looks like MIT-like and BSD licensing on all the components.
        Hide
        Klaus Trainer added a comment -

        Thanks for clarifying.

        Show
        Klaus Trainer added a comment - Thanks for clarifying.
        Hide
        Nuutti Kotivuori added a comment -

        This issue is about using something else than plain SHA hashing for: a) password hashing in couchdb configuration file, eg. local.ini, b) password hashing in _users database on disk storage. Cookie authentication hash method probably has a vulnerability as well, but that is something separate to solve and it is not what I wrote about here. Also I am not talking about online authentication attacks which are done through remotely exposed interfaces, but offline attacks that are possible when hashed passwords are obtained by some means.

        If access restrictions to _users database and configuration file are in place, the passwords stored there might just as well be in plaintext - which would be fine by me. Yet they aren't, which leads me to believe somebody thinks there is some actual security given by the hash method used in those places by CouchDB.

        So, to be clearer in my suggestion, I suggest the either of two options:

        1) use a standard slow hash function instead of current SHA-1 solution for storing passwords
        2) store passwords in plaintext, encoded in base64 (to prevent accidental exposure if shown to an admin)

        The current solution gives users a false sense of security and gains very little in practice.

        Show
        Nuutti Kotivuori added a comment - This issue is about using something else than plain SHA hashing for: a) password hashing in couchdb configuration file, eg. local.ini, b) password hashing in _users database on disk storage. Cookie authentication hash method probably has a vulnerability as well, but that is something separate to solve and it is not what I wrote about here. Also I am not talking about online authentication attacks which are done through remotely exposed interfaces, but offline attacks that are possible when hashed passwords are obtained by some means. If access restrictions to _users database and configuration file are in place, the passwords stored there might just as well be in plaintext - which would be fine by me. Yet they aren't, which leads me to believe somebody thinks there is some actual security given by the hash method used in those places by CouchDB. So, to be clearer in my suggestion, I suggest the either of two options: 1) use a standard slow hash function instead of current SHA-1 solution for storing passwords 2) store passwords in plaintext, encoded in base64 (to prevent accidental exposure if shown to an admin) The current solution gives users a false sense of security and gains very little in practice.
        Hide
        Klaus Trainer added a comment -

        Base64 is already used for basic authentication. A reason for using the hash function for cookie authentication is that you don't wanna have your password to be persitently stored in cleartext/Base64. If somebody manages to steal your cookie with that hash, she still doesn't have the password, and the hash is worthless anyway as soon as the session is closed/expired.

        If you need reasonable security, talk with your couch only through SSL and use a password that's not in a dictionary.

        The concern about somebody doing dictionary attacks on all _user DB entries can be met by restricting access to it.

        Btw., AFAIK, an authentication cache is already used.

        Show
        Klaus Trainer added a comment - Base64 is already used for basic authentication. A reason for using the hash function for cookie authentication is that you don't wanna have your password to be persitently stored in cleartext/Base64. If somebody manages to steal your cookie with that hash, she still doesn't have the password, and the hash is worthless anyway as soon as the session is closed/expired. If you need reasonable security, talk with your couch only through SSL and use a password that's not in a dictionary. The concern about somebody doing dictionary attacks on all _user DB entries can be met by restricting access to it. Btw., AFAIK, an authentication cache is already used.
        Hide
        Paul Joseph Davis added a comment -

        Alternatively, something that could be fun to play with the is the sort of thing that Zed Shaw was playing with on autho.me

        http://autho.me/

        That'd solve the issue of re-hashing on every request but its kinda not at all standardized.

        Show
        Paul Joseph Davis added a comment - Alternatively, something that could be fun to play with the is the sort of thing that Zed Shaw was playing with on autho.me http://autho.me/ That'd solve the issue of re-hashing on every request but its kinda not at all standardized.
        Hide
        Robert Newson added a comment -

        I think the point is that our current scheme is equivalent to plaintext passwords (the work factor is simply too low to quibble over).

        The overhead ought to be low enough, but we'll have to measure.

        BTW: I HATE new Jira. They appear to have overridden common key sequences (ctrl-a takes you to a custom Administration menu up there ^^ and not beginning-of-line like normal). Plus, my goodness, it's ugly.

        Show
        Robert Newson added a comment - I think the point is that our current scheme is equivalent to plaintext passwords (the work factor is simply too low to quibble over). The overhead ought to be low enough, but we'll have to measure. BTW: I HATE new Jira. They appear to have overridden common key sequences (ctrl-a takes you to a custom Administration menu up there ^^ and not beginning-of-line like normal). Plus, my goodness, it's ugly.
        Hide
        Nuutti Kotivuori added a comment -

        The issue is about using a secure hash function if the hash function serves a purpose at all! If it doesn't, please replace it with base64.

        Show
        Nuutti Kotivuori added a comment - The issue is about using a secure hash function if the hash function serves a purpose at all! If it doesn't, please replace it with base64.
        Hide
        Nuutti Kotivuori added a comment -

        Do note that plain HTTP authentication is somewhat problematic with these, as the password is sent as plaintext and the hash calculation has to be done by the server on each request. It's probably necessary to cache the authentication result for a certain plaintext password.

        Show
        Nuutti Kotivuori added a comment - Do note that plain HTTP authentication is somewhat problematic with these, as the password is sent as plaintext and the hash calculation has to be done by the server on each request. It's probably necessary to cache the authentication result for a certain plaintext password.
        Hide
        Klaus Trainer added a comment -

        Do you really think choosing a slow hash function would be a good idea, considering that CouchDB would have to take way more CPU cycles every time somebody authenticates?

        I'd approach that concern in a more pragmatic manner. For instance, you could protect the _users database, so that e.g. non-admins cannot read the salts and hashes.

        Show
        Klaus Trainer added a comment - Do you really think choosing a slow hash function would be a good idea, considering that CouchDB would have to take way more CPU cycles every time somebody authenticates? I'd approach that concern in a more pragmatic manner. For instance, you could protect the _users database, so that e.g. non-admins cannot read the salts and hashes.
        Nuutti Kotivuori created issue -

          People

          • Assignee:
            Robert Newson
            Reporter:
            Nuutti Kotivuori
          • Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development