安全的 PHP 上传表单和存储

信息安全 php
2021-08-25 20:52:27

我正在构建一个 PHP 应用程序,它允许上传文件(.doc/pdf 等)以供工作人员查看。其中一些文件有些机密,所以我需要保护它们。

现在最好的解决方案是让发件人在上传这些文件之前使用 GPG 或类似文件加密这些文件,并在另一端(在员工计算机上,而不是在 Web 服务器上)使用预共享密钥解密。

然而,期望所有客户都安装并学习使用 GPG 以上传文件是不现实的。

所以我能想到的最好的解决方案是:

1) 在受密码保护的页面上通过 HTTPS 上传文件。

2) 使用非对称 GPG 和存储在网络服务器上的公钥文件加密文件。

3) 删除 /tmp 等中文件的任何未加密副本。

4) 向工作人员发送电子邮件,通知他们该文件可供下载。

5) 工作人员登录并下载文件,服务器然后删除加密副本。

6) 工作人员然后使用未存储在网络服务器上的私钥解密文件。

这里的想法是,一旦网络服务器遭到破坏(它是一个专用服务器,因此不与其他人共享),攻击者将无法解密这些文件,因为他们不会在那里找到密钥。

然而:我认为这仍然是脆弱的。

因为,如果攻击者拥有 root 权限或什至只是控制 HTTP 服务器用户,他们将能够在文件仍在上传/加密的同时从 /tmp 读取数据,并制作未加密的副本,以便以后下载。

所以也许我可以在不写入/tmp 的情况下在内存中完成所有这些操作?但是这里仍然存在风险,攻击者可以通过自己上传文件来发现写入数据的内存地址,然后使用 ptrace 来检查和复制这些内存地址。

我想不出解决这个问题的方法,因为我需要明文数据才能进行加密。PHP中有没有办法让内存检查更难?或者有没有更好的第三方网络服务?

2个回答

所以也许我可以在不写入/tmp 的情况下在内存中完成所有这些操作?但是这里仍然存在风险,攻击者可以通过自己上传文件来发现写入数据的内存地址,然后使用 ptrace 来检查和复制这些内存地址。

正确安装的 SELinux 配置可以通过控制应用程序来降低受损机器的风险。最终,您必须确保机器安全。

我想不出解决这个问题的方法,因为我需要明文数据才能进行加密。PHP中有没有办法让内存检查更难?或者有没有更好的第三方网络服务?

在加密过程中的某个时刻,必须让传入的文件在内存中处于明文状态,这是根本无法解决的。然而,在内存中加密它肯定是要走的路。

您始终可以在浏览器前端使用 JavaScript 并在访问网络之前对其进行加密。您仍然必须使用 TLS 传输网页,以降低可能更改 Javascript 代码的 MITM 攻击的几率。

在浏览器端,您可以为每个会话生成唯一的 AES 密钥,然后通过 OpenSSL 使用后端工作人员的密钥对 AES 密钥进行加密,这样接收者就可以用自己的密钥解密对称密钥。

我可能会向您发送MEGA作为工作示例的参考。

好处

  • 通过使用 JavaScript,您将永远不会在内存中拥有解密文件。
  • 通过加密 AES 密钥,您将拥有更快的时间。
  • 客户端不需要 GPG。
  • 密钥是一次性的,因此他们需要破解与文档一样多的密钥。

保重

  • 密钥必须得到保护:在通过 OpenSSL 加密(然后被遗忘)之前,它们不应被写入永久存储。
  • 在任何攻击迹象中,记忆都应该是优先事项。要减少被盗的一次性 AES 密钥,请在第一次登录时终止网络服务器,然后重新启动它。用户只会看到一点停机时间。
  • JavaScript 传输和 AES 密钥生成和传输。
  • 浏览器扩展实际上可以修改您的 JavaScript。考虑将 JavaScript 捆绑为浏览器扩展,以更好地控制该部分。