Jump to content

Encryption


0x00

Recommended Posts

So, just had a quick play with the built in mysql encryption functions, here's the initial premise:

$tn=$db->prefix."priv_store";
$db->table_insert($tn, "'','Title 1',DES_ENCRYPT('my text data','password'),0");		//	1

$a=$db->raw("SELECT * FROM ".$tn."");
foreach($a as $e){
	echo "".$e['title']." :: ".htmlspecialchars($e['content'],ENT_QUOTES)."<br />\n";
}

echo "<br /><br />\n";

$a=$db->raw("SELECT title, DES_DECRYPT(content,'password') AS content FROM ".$tn."");
foreach($a as $e){
	echo "".$e['title']." :: ".htmlspecialchars($e['content'],ENT_QUOTES)."<br />\n";
}
When the data is first selected (without password), nothing is retrieved. Which at first glance is probably a good thing. However, at some point I want to offer backup features...

 

To start with when considering key storage my first thought was, if I store users passwords in the database then I may as well not encrypt the data... So my second thought was generate the key based on the users password as they log in and store this key in their session, but that blows the backup question out of the water because nothing is returned if incorrect password passed. I also wondered at the possibility of the case where a cracker has full access to the server and can grab the session files directly (?), also in some cases I do want to offer "stay logged in" feature.

 

Any ideas for this type of protocol? e.g. is it better to use mcrypt with PHP and store the result in the DB, even though that handles the backup situation it doesn't cover the session files. Am I wrong about not being able to get the encrypted data from the DB for backup? etc, etc...

Link to comment
Share on other sites

No this is for encryption of stored user content, not hashing.

 

Right, but the thing is - especially with passwords - you want to hash the submitted value before you send it over the line to the database. So use password_hash() before you insert the value into the database, then password_verify() after you retrieve it (and before you log a user in).

 

Also, encryption of passwords should be a one-way thing; you should never be able to decrypt a user's password. That way, if the database is compromised, the hacker isn't getting any useful password information.

 

If the user has forgotten their password, a new temporary one should be generated for a set amount of time, during which the user can log in to the system (using the auto-generated temporary password), and reset his or her permanent password. Which again, should be hashed (or encrypted - there's a difference between the two, but it's early and I can't rightly recall exactly what that difference is) before being sent to the database.

Link to comment
Share on other sites

The example implementation is pretty much the worst you can possibly do with regards to encryption. DES is a toy algorithm from the 70s which was deliberately weakened due to export restrictions. Last time I checked, it could be broken in less than a day. Then you use the infamous ECB encryption mode known from the Adobe hack. And finally you abuse a human-readable string as the “key”, turning the already shaky implementation into a joke. To be blunt: With this kind of encryption, you're better off storing the data as plaintext. That's at least honest.

 

Personally, I very much doubt that encryption even makes sense for the average website, because it's a lot of trouble for a very small benefit.

 

Without a hardware security module, proper key management is virtually impossible. You definitely cannot stuff your keys into the session files, because then you have a folder full of keys with no access control and no cache management (the session garbage collector only runs occasionally). So really the only option is to have a single application key which is used to encrypt the data before you store it in the database. But your database probably is on the same server as the application? Then your key is stitting right next to the ciphertext, which isn't very useful.

 

Implementing encryption with a low-level library like Mcrypt is also extremely difficult:

  • You need to choose an appropriate algorithm and a sensible cipher mode.
  • You have to generate a perfectly random initialization vector for every single plaintext and store it in the database.
  • Encryption doesn't prevent the data from being manipulated, which is most likely an issue as well. So now you have to worry about authenticated encryption.

This task is almost impossible for a layman, so you'll end up giving your users a false sense of security instead of actual security.

 

If at all, you'd use a high-level library. But then again: What's the concrete benefit?

Link to comment
Share on other sites

The login system is already as you two are describing, using one way hashing algorithms as signatures for passwords.

 

 

 

Here I'm encrypting (not hashing) actual data which will require to be decrypted, for this a password is required, the question is about how / where to store the user / site encryption password(s). (Personally I'd prefer passwords for each user.)

 

The issue is, if say use the login password (or some derivative of it) to encrypt / decrypt then it must be stored somewhere to be used after login, but the issue is the same if use a different password (e.g. at login use user pass to decrypt their encryption password), where to store it, especially with "stay logged in" situations.

 

 

I understand hashing and that its not actually encryption (as is generally banded about).

 

Here I'm trying to protect user data even if the system is breached at the shell level with escalated root privileges (i.e. they can grab sessions files from /tmp or otherwise). e.g. how to store (non login) passwords on a compromised system? Or even a protocol which keeps them secure from general DB or script hacks (e.g. with file IO as server user / group)

Link to comment
Share on other sites

The example implementation is pretty much the worst you can possibly do with regards to encryption. DES is a toy algorithm from the 70s which was deliberately weakened due to export restrictions. Last time I checked, it could be broken in less than a day. Then you use the infamous ECB encryption mode known from the Adobe hack. And finally you abuse a human-readable string as the “key”, turning the already shaky implementation into a joke. To be blunt: With this kind of encryption, you're better off storing the data as plaintext. That's at least honest.

 

Personally, I very much doubt that encryption even makes sense for the average website, because it's a lot of trouble for a very small benefit.

 

Without a hardware security module, proper key management is virtually impossible. You definitely cannot stuff your keys into the session files, because then you have a folder full of keys with no access control and no cache management (the session garbage collector only runs occasionally). So really the only option is to have a single application key which is used to encrypt the data before you store it in the database. But your database probably is on the same server as the application? Then your key is stitting right next to the ciphertext, which isn't very useful.

 

Implementing encryption with a low-level library like Mcrypt is also extremely difficult:

  • You need to choose an appropriate algorithm and a sensible cipher mode.
  • You have to generate a perfectly random initialization vector for every single plaintext and store it in the database.
  • Encryption doesn't prevent the data from being manipulated, which is most likely an issue as well. So now you have to worry about authenticated encryption.
This task is almost impossible for a layman, so you'll end up giving your users a false sense of security instead of actual security.

 

If at all, you'd use a high-level library. But then again: What's the concrete benefit?

 

I know its limitations and would prefer to use blowfish and have my choice of block mode (been a while I checked to see what algorithms mycrypt has, but it does give control over block mode).

 

As for perfectly random IV, well, I'll guarantee it to be unique for the key.

 

Data manipulation can be prevented using the right block mode!

 

 

 

As you say, storing in session files isn't secure, hence the initial question. Also the single application key is vulnerable to all the aforementioned if has root privileges (if considering key is initialised at mysql startup, e.g. when chrooted)

 

Even if using a standard package, say PGP, the key is required or required to be stored and encrypted by another...

Link to comment
Share on other sites

Here I'm encrypting (not hashing) actual data which will require to be decrypted, for this a password is required, the question is about how / where to store the user / site encryption password(s). (Personally I'd prefer passwords for each user.)

You could just store it in the database. But, you'll need to add the user's key to a static, secret site key in some way. If you simply use the user's key from the database to encrypt/decrypt, then the encryption is effectively useless because if there was a database breach, the attackers could just decrypt the data with the stored user key. If you add the user's key to a static site key, they would also have to compromise that key in order to decrypt.

Edited by scootstah
Link to comment
Share on other sites

What you want simply doesn't exist. Unless you're willing to spend thousands of dollars on dedicated crypto hardware, the best you'll get is some half-assed toy encryption. And you may not even get that.

 

 

 

I know its limitations and would prefer to use blowfish and have my choice of block mode (been a while I checked to see what algorithms mycrypt has, but it does give control over block mode).

 

Blowfish is obsolete as well, and Mcrypt is an incredibly poor library. If those are your choices, forget about it.

 

 

 

Data manipulation can be prevented using the right block mode!

 

What are you talking about?

 

 

 

Even if using a standard package, say PGP, the key is required or required to be stored and encrypted by another...

 

PGP/GPG never claimed to work on a compromised system. It doesn't.

Link to comment
Share on other sites

What you want simply doesn't exist. Unless you're willing to spend thousands of dollars on dedicated crypto hardware, the best you'll get is some half-assed toy encryption. And you may not even get that.

 Even simple encoding would defeat many script kiddies...

 

Blowfish is obsolete as well, and Mcrypt is an incredibly poor library. If those are your choices, forget about it.

 

 What would you suggest then?

 

 

What are you talking about?

 Some block modes use the previous block as an input, so if they are changed then what's after becomes useless, I'll read up as to which later, but see CBC here: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

 

 

PGP/GPG never claimed to work on a compromised system. It doesn't.

No, I wasn't saying it did, quite the opposite in fact.
Link to comment
Share on other sites

You could just store it in the database. But, you'll need to add the user's key to a static, secret site key in some way. If you simply use the user's key from the database to encrypt/decrypt, then the encryption is effectively useless because if there was a database breach, the attackers could just decrypt the data with the stored user key. If you add the user's key to a static site key, they would also have to compromise that key in order to decrypt.

 

And that's the point, on a fully compromised system, all the files are accessible too, even the root file used when starting up the database.

* You refer to the key, so you can have numerous keys for different purposes (https://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_des-encrypt ). I did wonder about the concept of rewriting the keyfile but that would require sudo privileges on the file that we're trying to protect, cyclic madness :D

 

 

However, storing a key in a file does protect in the case of only the db being compromised, not if they can write to php files or execute arbitrary code (or shell).

 

As you said, manipulating a site key with db user keys would provide a level of protection in the scenario of database compromise only.

Link to comment
Share on other sites

 Even simple encoding would defeat many script kiddies...

 

Script kiddies (as well as professional attackers) are defeated through secure programming and competent system administration, not toy cryptography.

 

Instead of wasting many days or even weeks on a highly questionable feature, it makes much more sense to spend a few hours on hardening the server. Do you have prepared statements everywhere? Content Security Policy? Clickjacking protection? Anti-CSRF tokens in all forms? Minimal database privileges? A separate PHP-FPM pool and Unix user for each website?

 

 

 

 What would you suggest then?

 

Secure programming competent system administration.

 

 

 

Some block modes use the previous block as an input, so if they are changed then what's after becomes useless, I'll read up as to which later, but see CBC here: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

 

CBC has nothing whatsoever to do with authenticity. It's actually trivial to make the first block produce arbitrary plaintext by changing the initialization vector, and the other blocks aren't protected either.

 

Authenticated encryption requires a correctly implemented combination of a cipher and a message authentication code (like Encrypt-then-MAC). There are also some special modes like AES-GCM which inherently provide authenticity, but those never made it into PHP, and I'm not aware of any plans to add them.

 

But why are we even discussing this? It's not the job of a web developer to implement cryptographic algorithms.

Link to comment
Share on other sites

A)

PHP-FPM TBH I dunno! The rest yes ;) We've discussed them :P

 

 

B)

But that's a different thread somewhere...

 

 

C)

No that's for hashes n such but it is for data tampering...

 

 

N)

Why not, I use a web portal for many webApp related api features, great for scoreboards n settings n such.

Link to comment
Share on other sites

However, storing a key in a file does protect in the case of only the db being compromised, not if they can write to php files or execute arbitrary code (or shell).

Of course not. If your physical box or codebase is compromised then all bets are off. If your app can encrypt/decrypt, then attackers can encrypt/decrypt too (if they have access to your box). There's not really any way to get around that, except to not let attackers compromise your box.

 

You have to take a step back and assess your realistic threat model here. What exactly are you protecting your data from? If you just want to protect data in your database and over-the-wire, then basic encryption as I've described should be sufficient. If you want to protect your server from NSA scrutiny, then no, you're in way over your head.

Link to comment
Share on other sites

C)

No that's for hashes n such but it is for data tampering...

 

What? I don't understand what you're saying.

 

 

 

N)

Why not, I use a web portal for many webApp related api features, great for scoreboards n settings n such.

 

That doesn't make you a cryptographer.

 

If you absolutely must have encryption, no matter how stupid it is, at least use a high-level library like libsodium which takes care of all the ugly details instead of relying on the developer to do that.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.