How secure is my system?

josh
  • How secure is my system? josh

    I am creating an application that allows a user to create an account, with a password, and have a set of public and private keys symmetrically encrypted with the password, so that they can be retrieved later when necessary, but only if the password is correctly entered.

    For both the password and the key pair, I am creating a salt derived from OpenSSL's random number generator.

    For the password, I am using bcrypt to encrypt with the aforementioned salt.

    For the key pair, it's a little more complicated. I am using OpenSSL with aes-128-ctr to encrypt the pair, and the key for aes is derived from the password and the salt. Specifically, here's the code I am using in Ruby:

    iter = 20000
    key_len = 16
    key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(password, salt, iter, key_len)
    # unhashed password and salt from before
    
    cipher = OpenSSL::Cipher.new('AES-128-CTR')
    cipher.encrypt
    cipher.key = key
    iv = cipher.random_iv
    cipher.iv = iv
    encrypted = cipher.update(data) + cipher.final #key pair
    

    My question is, is this system secure? Am I using best practices? As far as I can tell, I am, but I also want an outside opinion to ensure I'm not missing something major. If necessary I can provide the code for the password hashing, which is done using Ruby's bcrypt library.

    Edit: I want to clarify in case it is asked that I'm not asking about the validity of my code but the security of the code.

  • The whole setup seems kosher to me. But I feel that too little is known about the application itself; did you consider the possibility of the password being leaked, or the decoded keys?

    On some (web-based) systems, you'd have to "store" some or all of that data in a session object, which could well mean that the information is archived in plain text in a file on disk, or a key-value pair server, potentially accessible by other users as well as rogue processes, and possibly remaining accessible long after the user has logged out and disconnected. On such platforms you'd need to manually sanitize your data structures as far as possible; also, key-value assignment is non-trivial and typically requires a fairly unguessable session ID generator (which most aren't; unguessable, I mean).

    You appear to already know about this, but I'll refer to session fixation nonetheless. Also, memory databases and key-value stores might, for performance's sake, not properly initialize their memory and allow an attacker to recover sensitive data; typically you use low level API to request a 4K block, and read off it before initializing it. If the server did its homework properly you'll get 4096 zeroes. If it did not, you'll get whatever was stored in that block by the user before you (I saw this happen in a BANK, of all things).

    Then, access to those databases must be protected or secured somehow - a third party shouldn't be able to access data it has no right to (for example by enumerating stored datasets and querying their contents). On some systems you could use a different, totally unrelated (and vulnerable) virtual host to gain access to the content of such a keystore, by misdirecting the server into retrieving the wrong keyvalues. This caused an error, but sometimes the error text included precious information:

    We're sorry. There is no document called 
        *?=|1395481948749|1346625
       |lserni
       |62609098affb79cd2e7c31b6793b539e
       |Fl==SPQR].
    (Error: DB001A key was not found)
    Try using the Search function, or contact us with the details of this issue.
    

    Hypothetical example, attack #1

    website process with PID 12345 connects to keyserverd:
        >> "store value '<PRIVATEKEY>' into key 'pk-12345-1395494389'"
        << "OK"
    
    rogue process espies PID 12345 and knows the timestamp. It also connects:
        >> "Get me key 'pk-12345-1395494387'"
        << "ERROR: no such key"
        >> "Get me key 'pk-12345-1395494388'"
        << "ERROR: no such key"
        >> "Get me key 'pk-12345-1395494389'"
        << "OK: <PRIVATE KEY>"
    

    This may happen during the process lifetime, or can happen afterwards. Unless of course:

        >> "Logging out. Delete key pk-12345-1395494389"
        << "OK"
    

    Hypothetical example, attack #2

    Just as before, but this time the API is more complicated (at low level, of which you might not be aware):

    • application (to library): "Store value '' into key 'pk'"
      • library: generates unique pk-12345-1395494389
      • library: connects
      • library: requests 1880 bytes for pk-12345-1395494389
        • server: allocates 1880 bytes plus necessary housekeeping structures
        • server: returns handle 123
      • library: stores '' into handle 123 ...
    • application (to library): "Delete value 'pk'"

      • library: determine pk-12345-1395494389
      • library: deletes pk-12345-1395494389
        • server: marks 1880 bytes as "free" but DOES NOT OVERWRITE THEM
        • server: destroys handle 123
    • attacker: request 1880 bytes for key "pwn"

      • server: allocates 1880 bytes plus ... and these are THE SAME BYTES FREED A MOMENT AGO
    • attacker: does NOT write anything to key 'pwn'
    • attacker: read content of "pwn" memory block (sometimes this is not allowed, but the memory is nonetheless accessible in some roundabout way. Some other times it isn't, but you can't count on getting a break)
    • attacker: finds "" (or sometimes "@#£!VATE KEY>")

    In such a case:

        >> "Logging out. Store '##[...1.8Kb of #'s...]###NICE TRY!' 
                    into key pk-12345-1395494389"
        << "OK"
        >> "Delete key pk-12345-1395494389"
        << "OK"
    

    is slower, but more secure ("memory shredding" or "memory scrubbing").

    In such a scenario, storing data to the database is as good as having passwords in cleartext; actually it's worse, because while a user must have file system access to the database files or authentication to the database server in order to reap the passwords, in many instances keystores are designed for "we're among friends" access, and anybody with local access can retrieve data (e.g. Redis "is designed to be accessed by trusted clients inside trusted environments"). This is OK, mind you, as long as you know what's happening and take countermeasures. After all, the Internet is insecure and yet here we are creating websites - but we use authentication and SSL when we need them, for we know of the insecurity. With Redis for example we could turn on authentication; now the attacker has to have both local access and the password, but the password is in the webapp files, so he needs read access to those files, too. If we make it so that this equals to impersonating the webapp user, we're (more or less) done: because a local attacker with webapp impersonation capabilities could just ask the password to any user and/or mount a man-in-the-middle attack. Of course this is all very, very rough; you need to examine your own workflow and ask yourself, "What could one do who arrived at this point? What else could he do? How do I take him out? How do I keep him out?".

    Desktop applications also have their own insecurities related to password and plaintext data persistence both in memory and on disk (you have to treat specially the sensitive memory region to prevent it from being cleartext swapped on disk, and have to scrub the memory manually before freeing).

Tags
encryption openssl
Related questions and answers
  • , with the smartcard unavailable, I have to make sure I have a private key available on server B. Therefore, I created a password-protected RSA ssh key pair with on server B using ssh-keygen -t rsa The password is verylongandcomplicatedpassword. Thus, I don't want to type it a lot. I appended the public key .ssh/id_rsa.pub to .ssh/authorized_keys on server A as well as on server B. Using ssh from server B... on server B and authenticate with my smartcard. I want the same thing for server A, because server B is unreachable from site 2, where I also work sometimes. gpg-agent is started as a Startup item using

  • I am making a web app and I'm now stuck on making the login secure. I'm thinking of adding a salt to a user-inputted password and then hash it. (md5 or sha for example) and then I will reshuffle the results. eg: $salt = "hello"; $password = "password"; $newpassword = md5($salt.$password); //lets assume the result is 1234567890 I will reshuffle the order of the hash like exchanging the first and last character then 3rd and 3rd to the last. the result will look like: 0284567391 Does this make the password more secure? Please don't suggest some hardcore encryption stuffs. I just need

  • I am currently trying to build a little, secure password manager. As of now, I've implemented the encryption. Each website has its own file and each file has a number of fields (Most commonly username and password). I am using serpent 256 to encrypt the files, and I use a random key (created Crypto.Random in python) that is encrypted using GPG, with a 4k key. Side question: The key is sha256 hashed in order to be able to enter whatever size you want ('cause sha256 always has 256 bit result), do I lose any entropy/security/etc.? My main question, is how can I securely transfer the decrypted

  • then these wacky hashes still function as secure hashes, and our system doesn't break Kerckoffs's principle anymore than it would with a standard hash. Here are two possible (and worthwhile, as far as I can see) advantages to using a "wacky" hash over a normal hash: Sure, your system should be secure if the attacker has the source code, but it's a very likely possibility that your attacker wont have... and over again I still don't understand the logic. Here are some examples: md5(md5(salt) + bcrypt(password)) scrypt(bcrypt(password + salt)) sha1(md5(scrypt(password + md5(salt)))) The typical

  • to anyone and keep it under my pillow at night, and also assume the NSA doesn't break into my house to chloroform me and install a targeted exploit) I'm far from being a crypto expert, but I spent some time reading Wikipedia on AES, block cipher modes and key derivation algorithms, and I also read "If You're Typing The Letters A-E-S Into Your Code, You're Doing It Wrong". All this has made me... The Letters A-E-S Into Your Code, You're Doing It Wrong" points out the dangers of an attacker who has control over the encryption process, i.e. who can supply arbitrary plaintext and have it encrypted

  • line of thinking. Please validate. Keep the salt argument to the method pbkdf2 (in the code snippet above) secret (obtain it from a highly secure HSM as opposed to storing it in the database alongside... of the key and a random bytes generated from a CSPRNG. [salt] = [secret key] + [random bytes from a CSPRNG] Finally, I will dare to ask a silly question (will dare to ask since high iteration count...As mentioned in this wonderful link, the way to get a PBKDF2 Hash of a user given password given a password (of course), a salt (generated Cryptographically Secure Random Number Generator

  • rather than a hash algorithm. So there must be a hard-coded key somewhere to use bcrypt, and since Blowfish is being used, it stands to reason that if the key is discovered, the password derivation can be reversed and the original password discovered. Since client-side code can be decompiled, the key could be easily discovered, making bcrypt unsafe to use client-side. Is my reasoning correct or have I...I am concerned about the use of bcrypt for client-side password generation. I am developing a password generation function to be used client-side, similar to PwdHash and PasswordMaker. Much has

  • to accommodate application-specific passwords (create an encrypted private key per password), in case I ever want to develop apps besides the web interface. My question is: How fundamentally (in)secure... (and thus decrypting the file) is encrypted using a secret based on the user's password. This means that files can only be read by the server if the decrypted private key is kept in its decrypted form...I am thinking of creating a cloud-based document archive. The intention is to make it impossible for the system to read the users' files, and be more than just a storage provider. Looking

  • users (scaling to millions). All user data will be encrypted on a per-user basis with standard encryption. The password-protected encryption keys will be stored on a remote secure keyserver, which.... We are using AES-256 symmetric encryption, but the fundamental problem remains even for a PKI solution, as you still need to secure the private key. Note also that we could use a keystore instead... interaction should be minimized, since we want servers to start and restart as automatically as possible to reduce any downtime or human errors. My guess is that manual interaction may be necessary

Data information