1

I am considering creating a web-based KeePass-like solution in Symfony 3 (PHP) to have the password safe with few other functionalities added. I want to make sure there are no major security flaws. Here are the assumptions:

  1. Internal company server, internal service
  2. Website works on HTTPS only
  3. User first needs to log in (LDAP, company's password policy is quite strict)
  4. After logging in, user needs to enter encryption password which will be used as the encryption key after being hashed with SHA256 (hash('sha256', $key, true))
  5. The entered encryption password is checked if valid by comparing a single decrypted value with known expected value
  6. Encryption/decryption methods, used for keeping/retrieving passwords from the DB:

    public function encrypt($openText) {
        $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        $iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
    
        $encryptedPayload = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->keyHash, $openText, MCRYPT_MODE_CBC, $iv);
    
        $encryptedBinary = $iv . $encryptedPayload;
    
        return $encryptedBinary;
    }
    
    public function decrypt($encryptedBinary) {
        $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        $iv = substr($encryptedBinary, 0, $ivSize);
    
        $encryptedPayload = substr($encryptedBinary, $ivSize);
    
        $openText = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->keyHash, $encryptedPayload, MCRYPT_MODE_CBC, $iv), "\x00");
    
        return $openText;
    }
    
  7. Encryption key hash is kept in user session

  8. User session expires after 120 seconds since last activity
  9. Passwords are not kept in website HTML - they are read from the server every time using AJAX over HTTPS, temporarily put in HTML element's attribute to be copied by JS, and then the attribute gets removed
  10. Passwords are copied to clipboard using clipboard.js
  11. Clipboard is cleared (by copying empty string) after 15 seconds

Do you see any security problems here (considering webapp design, compared to KeePass)? What should I be paying special attention to?

3
  • 3
    Use a password hashing algorithm like bcrypt instead of SHA256.
    – Noir
    Aug 23, 2016 at 14:22
  • 1
    What about making a client-side app instead of a web-based tool? The problem with web is that if the server becomes evil all the passwords are compromised because it would just serve malicious JS that would capture the secret key. With a native app the server would have to publish a compromised version of the app and convince users to install it before it can get access to the passwords. Aug 23, 2016 at 14:51
  • Also consider that you are introducing potentially unwanted complexity by using a web browser as a client. This could result in a ridiculously big attack surface unless hardening and patch management are implemented properly.
    – Noir
    Aug 24, 2016 at 6:38

2 Answers 2

4

Lots of potential problems here.

First, you're using PHP, and it's hard to do things correctly (like avoiding SQL injection, encrypting securely, etc.) in PHP. It's not impossible, by any means, but it's unreasonably difficult.

Second, as a commenter pointed out, you're hashing a password with SHA256 to generate the key. This is bad. Use a proper PBKDF, like bcrypt.

Third, you're using the 256-byte block-size version of Rijndael, which is just odd. Don't, like so many others have before you, confuse this with AES-256.

Fourth, don't encrypt the data directly with the derived key. Encrypt it with a data encryption key which is securely randomly generated, and which then in turn is protected with the user's password derived key. This way the user can change their master encryption password without you then having to synchronously decrypt all of their passwords with the old key, and re-encrypt them with the new key. You only need to re-encrypt the data-encryption-key with the key-encryption-key.

Fifth, logging, rate-limited, IDS. You need to have a system in place to dampen attacks, and let you know when their happening.

That's enough for now. I'm sure there are many more pitfalls...This is just a list from my initial glance. I would strongly encourage you to abandon this project entirely, and look for an existing, reasonably well proven solution like 1Password for Teams, or something along those lines instead. Building a system like this is fraught with danger, and the code sample you provided indicates to me that you probably do not yet have the knowledge required to accomplish it with any reasonable level of confidence in its security. And that's not a knock against you...These are simply incredible difficult systems to build securely, and someone attempting to do it for the first time without guidance beyond what the Internet can provide, won't.

1
  • Thank you for your reponse. About 3rd, I found this must-read for all people like me: paragonie.com/blog/2015/05/… . I want to ask you to elaborate on difficulty to do things in PHP correctly. SQL injection is easy to do in any language, it's not a PHP weak point. I am aware of possible configuration (php.ini) flaws, which are PHP-specific. Or the old mcrypt. Configuration and old modules, is there anything other that can be a gotcha? Or did you mean something completely different?
    – Veelkoov
    Sep 4, 2016 at 15:56
1

You are missing a code review. Keepass is open-source and has been independently reviewed.

Even if the design is correct, getting the implementation right is extremely difficult.

Consider the cost of an audit.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .