5

介绍

我目前正在从事一个项目,该项目涉及每天从 VisualFox Pro 数据库中提取数据(药房记录),并将其中的一些上传到 WordPress 网站,药房的客户可以安全地查看它。我想就我的软件的一般方法获得一些建议——我可以编写代码,但需要知道我是否走对了路。我正在编写 PC 软件(在 C#/.NET 4.5 中)和 PHP WordPress 插件。

问题一:加密

我打算使用的当前加密数据服务器端的过程是基于这篇文章。总而言之,它提倡使用存储在服务器上的自己的公钥对每个单独用户的数据进行非对称加密。然后,用于解密此数据的私钥本身使用用户的密码进行对称加密并存储。这样,即使数据库被盗,也需要破解用户的密码哈希,甚至需要对每个用户的数据重复该过程。

作者自己指出的唯一弱点,也是我问题的重点,是当用户登录时,解密的密钥存储在会话存储中。文章建议的处理方式是限制用户登录的时间。我认为更好的解决方案是将该密钥存储在一个短暂的安全 cookie 中(当然整个过程是通过 HTTPS 进行的) . 这样,如果攻击者控制了用户的计算机并且可以读取他们的cookie,他们可能只需要输入密码并登录,而无需窃取数据库,而即使攻击者获得了对服务器的访问权限,他们也无法解密HTTPS 流量(或者可以吗?我不确定。)

我应该使用安全 cookie 还是会话存储来临时存储解密的密钥?

问题 2:存储

我还想解决的第二件事是如何存储数据——这更像是一个效率问题。由于每个用户都有自己的加密密钥,因此每个用户的记录必须单独存储。我不知道我是否应该为每个用户存储一个“块”数据,其中包含带有表示记录的对象数组的加密 JSON,或者我是否应该将记录存储在具有实际数据结构的表中,并加密每个数据字段与钥匙分开。

我倾向于将数据存储为一个块 - 在我看来,一次解密一大块数据似乎比数千个单独的字段更有效。此外,即使我以正确的结构存储数据,我仍然无法使用 MySQL 的 WHERE、ORDERBY 等,因为数据都是 BLOB。

我应该将数据存储为每个用户的大块,还是分成不同的字段?

问题3:转移

我从 DBF 文件中提取数据,本质上是做一个“差异”,我比较从前一天的数据中提取的当前数据,只上传已经改变的用户块(我不能只上传记录,因为我可能最终会将用户的数据存储在块中)。我还包括已删除用户的“删除”说明。这是因为数据库中有数十万条记录,总计超过 200mb,并且大小每天都在增加。

我目前的计划是将所有这些数据写入一个 JSON 文件,gzip 并将其上传到服务器。我的问题是,如何在确保数据安全的同时做到这一点?自然,上传将通过 HTTPS 进行,并且我有一个 API 密码,仅允许授权上传,但我主要关心的是如果服务器受到破坏,如何保护数据。我不希望攻击者在处理 JSON 文件时从服务器中获取它。我的一个想法是让服务器向我发送用户的公钥列表,并在上传之前在我的软件中执行加密。在我看来,这是保护这些数据的唯一方法。我可以加密整个 JSON 文件,可能使用 API 密钥或特殊密码,但如果攻击者可以直接访问解密文件,那就没有意义了 s 在服务器上处理。这是一个好的解决方案吗?

我应该在客户端单独加密数据,还是有办法将其安全地传输到服务器并在那里加密?

提前感谢您的任何答案,我很想听听以前处理过此类问题的人的意见。

注意:交叉发布给程序员,请参阅评论。

4

1 回答 1

3

问题 1

加密

碰巧的是,我正在开发一个类似的系统来加密 Wordpress 评论中的个人详细信息(电子邮件、IP),这样如果服务器遭到入侵,数据库中的敏感数据仍然会被加密。在会话中存储非对称解密密钥对我来说是不可能的,因为这可能会将密钥留在服务器上,让攻击者在破坏它的同时获取。

因此,基于 SSL 证书的 cookie 是一种更好的方法——至少攻击者必须等待用户登录才能窃取他们的密钥。与此同时,某种绊线系统将是一个好主意,这样一旦系统受到破坏,用户就无法登录系统(从而将他们的密钥提供给等待的攻击者)。

正如您所说,加密记录(根据我的设计使用一个密钥,或者根据您的设计使用多个密钥)意味着搜索记录成为您必须远离数据库服务器的过程,这反过来意味着它将显着慢点。

您可以通过在速度和安全性之间进行权衡来缓解这种情况:某些字段可以被模糊化,然后不加密地存储。例如,如果您想搜索您的患者所在的位置,从他们的地址获取他们的(纬度,经度),对其应用随机偏移(例如在任一方向上的两个轴上最多 3 英里),然后存储结果坐标纯文本。然后可以在不解密的情况下完成与位置相关的近似计数查询。

缓解对客户端计算机的攻击

上面介绍了如何减轻对服务器的攻击,这是您面临的最大风险,因为您的所有记录都存储在那里。正如您正确指出的那样,对客户端计算机的攻击也是一个问题,如果他们是公众成员,那么可以假设他们的安全过程不存在。

在此基础上,您可以使用密码短语强化单个密码(完整给出),客户端需要从中选择三个随机字母(即特别没有完整给出)。这以两种方式优雅地抵御键盘记录器:首先使用下拉菜单,这更难窃听,即使用户使用键盘快捷键,他们也没有提供完整的短语。每次成功登录时,随机字母(如1、4、5)的索引都会被记录下来,并且很长一段时间内不再询问。显然,太多错误的答案会导致帐户被锁定,并需要通过电话或蜗牛邮件重置代码重新授权。

您可以使用的其他身份验证方法:每次输入正确密码时向用户发送一个额外的密码,或者(可能非常昂贵)根据网上银行使用身份验证设备。

存储很少/不存储识别信息

另一个安全提示是尽可能少地存储个人信息。如果您无法通过电子邮件立即重置密码,那么姓名、地址、电话号码和电子邮件——所有个人识别数据——可能都是不必要的。该个人信息可以单独存储在另一台服务器上的断开连接的数据库中,使用公共主键将它们链接在一起。(事实上​​,如果用户希望重置他们的密码,您可以简单地在他们的匿名用户记录中存储一个标志,并且药剂师可以在他们下次访问管理面板时在他们的防火墙机器上手动运行重置过程)。

问题2

您应该在一个 blob 中加密表格数据还是将其保留在每一列中?我在我的应用程序中也看过这个。对我来说,我将它存储在一个 blob 中,因为我的用例是搜索密集型的,并且每行有 N 个解密而不是一个解密使决策变得容易。也就是说,您可能更喜欢单独加密列的整洁性,并且有人可能会争辩说,如果腐败蔓延,将它们分开会给您更好的机会使某些行能够存活。

如果您决定存储在单个 blob 中,我将使用与此类似的格式(在非对称加密之前用换行符分隔的行):

1.2      <-- version of this format, so I can add things in the future
key1=value1
key2=value2
...

如果您有多个进程写入列,请确保在读取和写入之间锁定行,否则(如上所述)您可能会丢失一些数据。

正如您所说,这同样可以是 JSON,如果该格式更适合您。

问题 3

我对这个问题的理解是:鉴于您自己无法解密用户记录,您如何复制到未加密的离线副本?我在这里想知道您是否可以稍微放松一下安全限制,并在服务器上存储一个公共公钥,并单独记录使用该公共密钥加密的更改。这将填充一个应该定期清空的表(通过在远程安全机器上运行同步例程);因此,与获取未加密的整个数据库相比,更改表对攻击者的价值将很小。

当然,相应的私钥应该在药剂师的计算机上,再次安全地从互联网防火墙。

这种设计的风险是攻击者用他/她自己的公钥替换服务器公钥,以便他们以后可以收集已经为他们有效加密的信息!然而,只要你在服务器上安装了trip-wire,就可以合理防御:如果触发了这个,web应用程序的动态部分不会写任何新的变化(实际上不会工作)完全),直到系统被扫描并确定是安全的。

于 2013-02-21T20:53:31.533 回答