Goal:
I'd like to allow users to create questions and collect information from other users in a custom web app (PHP/MySQL in a shored hosting environment) and protect the data collected.
我想允许用户在自定义Web应用程序(支持托管环境中的PHP / MySQL)中创建问题并从其他用户收集信息,并保护收集的数据。
Background:
The default questions that all users answer are general enough that they can not be construed as personally identifiable information (PII), thus limiting my liability to protect it, but users who create their own questions will likely ask for PII which then becomes a liability.
所有用户回答的默认问题都是足够通用的,不能将其视为个人身份信息(PII),从而限制了我保护它的责任,但是创建自己问题的用户可能会要求PII,然后成为负债。
What I would like to do is protect this information in such a way that if either the hosting account or the database were compromised (or both!), the PII would not be recoverable without a significant amount of work, and even then, only a small portion would theoretically be recoverable.
我想要做的是保护这些信息,如果托管帐户或数据库被泄露(或两者兼而有之!),如果没有大量的工作,PII将无法恢复,即便如此,只有从理论上讲,小部分是可以恢复的。
Proposed solution:
Assuming MySQL's built-in AES_ENCRYPT()/AES_DECRYPT()
functions are used to encrypt the PII table, the passphrase would need to be stored in the hosting account, so if the hosting account were compromised, the data could easily be read.
假设MySQL的内置AES_ENCRYPT()/ AES_DECRYPT()函数用于加密PII表,密码需要存储在主机帐户中,因此如果托管帐户被泄露,则可以轻松读取数据。
Since the users' passwords are well protected (hashed with salt), I'm thinking of capturing their plaintext password during authentication, encrypting it, and storing it in the PHP session until the user logs out.
由于用户的密码受到良好保护(使用盐进行哈希处理),我正在考虑在身份验证期间捕获明文密码,对其进行加密,并将其存储在PHP会话中,直到用户注销为止。
A public/private key combo will be created for each user with the private key being password protected with the user's password + salt.
将为每个用户创建一个公钥/私钥组合,其中私钥由用户的密码+ salt密码保护。
Then, when PII data based on that user's custom questions are added to the DB, the user's public key would be used to encrypt the PII that they collected through the app. When the data is read (only when the user is logged in), the data would be unencrypted with the user's private key (which is unlocked with their password + salt).
然后,当基于该用户的自定义问题的PII数据被添加到DB时,用户的公钥将用于加密他们通过应用程序收集的PII。读取数据时(仅当用户登录时),数据将使用用户的私钥(使用密码+ salt解锁)进行解密。
The benefits I see are:
我看到的好处是:
- in the worst case scenario, where servers completely compromised, app code is read to find encryption keys, PHP session files are decrypted to find user's passwords, then entries in the PII table associated with that user are decrypted, then only the PII collected from questions of currently logged-in users could be recovered. Any users not logged in would be safe.
- even the DBA or similar wouldn't be able to read the PII.
在最糟糕的情况下,服务器完全泄露,读取应用程序代码以查找加密密钥,解密PHP会话文件以查找用户密码,然后解密与该用户关联的PII表中的条目,然后仅从问题中收集PII当前登录的用户可以恢复。任何未登录的用户都是安全的。
即使是DBA或类似的人也无法阅读PII。
The drawbacks I see are:
我看到的缺点是:
- user passwords are stored in a recoverable form while they are logged in.
- users who forget their passwords would loose access to their data.
- each relatively small bit of data will take up much more space in the DB due to encryption.
用户密码在登录时以可恢复的形式存储。
忘记密码的用户将无法访问其数据。
由于加密,每个相对较小的数据将占用DB中更多的空间。
My question: Is there a better way to do this?
我的问题:有更好的方法吗?
2 个解决方案
#1
6
I see a number problems with this design from a security perspective. First of all passwords must never be encrypted, this is a vulnerability identified by CWE-257.
从安全角度来看,我看到了这个设计的一些问题。首先必须永远不加密密码,这是CWE-257识别的漏洞。
Further more MySQL's AES_ENCRYPT()
is complete garbage for more than one reason. It uses EBC mode, and here is a good example of why this is crap:
更多MySQL的AES_ENCRYPT()完全是垃圾,原因不止一个。它使用EBC模式,这是一个很好的例子,为什么这是废话:
Original Image:
EBC Mode (which is what mysql's AES_ENCRYPT()
uses):
EBC模式(这是mysql的AES_ENCRYPT()使用的):
But if the database where compromised the attacker is going to defeat AES_ENCRYPT()
by enabling the query log.
但是,如果攻击者受到攻击的数据库将通过启用查询日志来打败AES_ENCRYPT()。
Using the user's password for encryption should be avoided, you should be using a crypgoraphic nonce. If you do use a password make sure you use a String2Key funciton. You must also use CBC or CMAC mode with a random iv. I don't really see how asymmetric cryptography can help. Asymmetric cryptography is very slow, memory intensive. They data that it protects is made less secure when the attacker controls the message because you can compare cipher text messages. This is why an random IV is important, and in the asymmetric world you don't have this level of protection.
应该避免使用用户的密码进行加密,你应该使用crypgoraphic nonce。如果您使用密码,请确保使用String2Key功能。您还必须使用随机iv的CBC或CMAC模式。我真的没有看到非对称加密技术如何提供帮助。非对称加密非常缓慢,内存密集。当攻击者控制消息时,它们保护的数据会降低安全性,因为您可以比较密文消息。这就是随机IV很重要的原因,而在非对称世界中,你没有这种保护级别。
Key Generation should look something like: $key=string2key($base_nonce.$salt.$user_password)
密钥生成应该类似于:$ key = string2key($ base_nonce。$ salt。$ user_password)
Make sure the output of your string2key function is the same size as your keyspace. So aes 128 needs a 128bit key. Each password should have its own $salt
, and the $base
is a cryptographic nonce stored in textfile. (An attacker would have to read this file before he can crack the key, if this value is large like 128 bits then its a moot point.) Each message needs its own $iv
and this value must also be a cryptographic nonce (similar to a salt). I would generate the $salt
,$iv
and $base_nonce
from /dev/urandom
. The IV can be stored in plain text in a column in your database along with the cipher text.
确保string2key函数的输出与键空间的大小相同。所以aes 128需要128位密钥。每个密码都应该有自己的$ salt,而$ base是存储在textfile中的加密nonce。 (攻击者必须先读取此文件,然后才能破解密钥,如果此值大到128位,那么它就是一个有争议的点。)每条消息都需要自己的$ iv,这个值也必须是加密的nonce(类似于盐)。我会从/ dev / urandom生成$ salt,$ iv和$ base_nonce。 IV可以以明文形式存储在数据库的列中,也可以与密文一起存储。
From a legal standpoint even if you build a secure cryptogrpahic system you still have problems with insider threats and if the server is completely compromised, all of the data will still be compromised. This really isn't an engineering problem.
从法律角度来看,即使您构建了一个安全的cryptogrpahic系统,您仍然会遇到内部威胁问题,如果服务器完全受损,所有数据仍然会受到损害。这确实不是一个工程问题。
The best defense against a legal threat is a strong Terms and Conditions written by a skilled lawyer.
对法律威胁的最佳防御是由熟练的律师撰写的强有力的条款和条件。
#2
0
One concern I'd have is the following. The "any users not logged in would be safe" part is too optimistic. By protecting the private key with the user's password, you open yourself up to various password brute-forcing attacks. Not just for current sessions, but for all. One effective one is to simply enumerate the top 100 common passwords, say, and just try them out against all users. Attacker is bound to uncover some keys. (I'm assuming that you're either storing per-user random salt with the user record, which the attacker can see, or else that you have a secret salt that the attacker was able to obtain through the compromise.)
我所关注的一个问题如下。 “任何未登录的用户都是安全的”部分过于乐观了。通过使用用户密码保护私钥,您可以打开各种密码强制攻击。不只是为了当前的会议,而是为了所有人。一个有效的方法就是简单地列举前100个常用密码,然后尝试对所有用户进行尝试。攻击者必然会发现一些密钥。 (我假设您要么将每用户随机盐与用户记录存储在一起,攻击者可以看到,或者您有一个攻击者能够通过妥协获得的秘密盐。)
#1
6
I see a number problems with this design from a security perspective. First of all passwords must never be encrypted, this is a vulnerability identified by CWE-257.
从安全角度来看,我看到了这个设计的一些问题。首先必须永远不加密密码,这是CWE-257识别的漏洞。
Further more MySQL's AES_ENCRYPT()
is complete garbage for more than one reason. It uses EBC mode, and here is a good example of why this is crap:
更多MySQL的AES_ENCRYPT()完全是垃圾,原因不止一个。它使用EBC模式,这是一个很好的例子,为什么这是废话:
Original Image:
EBC Mode (which is what mysql's AES_ENCRYPT()
uses):
EBC模式(这是mysql的AES_ENCRYPT()使用的):
But if the database where compromised the attacker is going to defeat AES_ENCRYPT()
by enabling the query log.
但是,如果攻击者受到攻击的数据库将通过启用查询日志来打败AES_ENCRYPT()。
Using the user's password for encryption should be avoided, you should be using a crypgoraphic nonce. If you do use a password make sure you use a String2Key funciton. You must also use CBC or CMAC mode with a random iv. I don't really see how asymmetric cryptography can help. Asymmetric cryptography is very slow, memory intensive. They data that it protects is made less secure when the attacker controls the message because you can compare cipher text messages. This is why an random IV is important, and in the asymmetric world you don't have this level of protection.
应该避免使用用户的密码进行加密,你应该使用crypgoraphic nonce。如果您使用密码,请确保使用String2Key功能。您还必须使用随机iv的CBC或CMAC模式。我真的没有看到非对称加密技术如何提供帮助。非对称加密非常缓慢,内存密集。当攻击者控制消息时,它们保护的数据会降低安全性,因为您可以比较密文消息。这就是随机IV很重要的原因,而在非对称世界中,你没有这种保护级别。
Key Generation should look something like: $key=string2key($base_nonce.$salt.$user_password)
密钥生成应该类似于:$ key = string2key($ base_nonce。$ salt。$ user_password)
Make sure the output of your string2key function is the same size as your keyspace. So aes 128 needs a 128bit key. Each password should have its own $salt
, and the $base
is a cryptographic nonce stored in textfile. (An attacker would have to read this file before he can crack the key, if this value is large like 128 bits then its a moot point.) Each message needs its own $iv
and this value must also be a cryptographic nonce (similar to a salt). I would generate the $salt
,$iv
and $base_nonce
from /dev/urandom
. The IV can be stored in plain text in a column in your database along with the cipher text.
确保string2key函数的输出与键空间的大小相同。所以aes 128需要128位密钥。每个密码都应该有自己的$ salt,而$ base是存储在textfile中的加密nonce。 (攻击者必须先读取此文件,然后才能破解密钥,如果此值大到128位,那么它就是一个有争议的点。)每条消息都需要自己的$ iv,这个值也必须是加密的nonce(类似于盐)。我会从/ dev / urandom生成$ salt,$ iv和$ base_nonce。 IV可以以明文形式存储在数据库的列中,也可以与密文一起存储。
From a legal standpoint even if you build a secure cryptogrpahic system you still have problems with insider threats and if the server is completely compromised, all of the data will still be compromised. This really isn't an engineering problem.
从法律角度来看,即使您构建了一个安全的cryptogrpahic系统,您仍然会遇到内部威胁问题,如果服务器完全受损,所有数据仍然会受到损害。这确实不是一个工程问题。
The best defense against a legal threat is a strong Terms and Conditions written by a skilled lawyer.
对法律威胁的最佳防御是由熟练的律师撰写的强有力的条款和条件。
#2
0
One concern I'd have is the following. The "any users not logged in would be safe" part is too optimistic. By protecting the private key with the user's password, you open yourself up to various password brute-forcing attacks. Not just for current sessions, but for all. One effective one is to simply enumerate the top 100 common passwords, say, and just try them out against all users. Attacker is bound to uncover some keys. (I'm assuming that you're either storing per-user random salt with the user record, which the attacker can see, or else that you have a secret salt that the attacker was able to obtain through the compromise.)
我所关注的一个问题如下。 “任何未登录的用户都是安全的”部分过于乐观了。通过使用用户密码保护私钥,您可以打开各种密码强制攻击。不只是为了当前的会议,而是为了所有人。一个有效的方法就是简单地列举前100个常用密码,然后尝试对所有用户进行尝试。攻击者必然会发现一些密钥。 (我假设您要么将每用户随机盐与用户记录存储在一起,攻击者可以看到,或者您有一个攻击者能够通过妥协获得的秘密盐。)