17

攻击

在凭证存储环境中,一种可能的威胁模型是攻击者,它具有以下能力:

  • 检查任何(用户)进程内存
  • 读取本地(用户)文件

AFAIK,对这种类型的攻击的共识是无法防止(因为凭据必须存储在内存中以供程序实际使用它们),但是有几种技术可以减轻它:

  • 最小化敏感数据在内存中的存储时间
  • 一旦不再需要数据就覆盖内存
  • 通过隐蔽措施破坏内存中的数据,继续移动它和其他安全措施

特别是 Python

第一种技术很容易实现,可能通过密钥环 (希望是内核空间存储)

据我所知,如果不编写 C 模块,第二个是根本无法实现的(但我很想在这里被证明是错误的,或者有一个现有模块的列表)

第三个很棘手。

特别是,python 是一种具有非常强大的自省和反射能力的语言,很难阻止任何可以在解释器进程中执行 python 代码的人访问凭据。

似乎有一种共识,即没有办法强制执行私有属性,并且尝试这样做最多只会惹恼正在使用您的代码的其他程序员

问题

考虑到所有这些,如何使用 python 安全地存储身份验证凭据?最佳实践是什么?可以对“一切都是公共的”哲学做些什么吗?我知道“我们在这里都是成年人”,但我们是否应该被迫在与攻击者共享密码和使用另一种语言之间做出选择?

4

2 回答 2

31

存储身份验证凭据的原因有两个:

  1. 对您的用户进行身份验证:例如,您仅在用户对您的程序进行身份验证后才允许用户访问服务
  2. 使用另一个程序或服务对程序进行身份验证:例如,用户启动您的程序,然后使用 IMAP 通过 Internet 访问用户的电子邮件。

在第一种情况下,您永远不应该存储密码(或密码的加密版本)。相反,您应该使用高质量的盐对密码进行哈希处理,并确保您使用的哈希算法计算量大(以防止字典攻击),例如 PBKDF2 或 bcrypt。有关更多详细信息,请参阅Salted Password Hashing - Doing it Right 。如果你遵循这种方法,即使黑客检索到了加盐的、散列缓慢的令牌,他们也不能做太多事情。

在第二种情况下,采取了许多措施来使秘密发现变得更加困难(正如您在问题中概述的那样),例如:

  • 将机密加密直到需要,按需解密,然后立即重新加密
  • 使用地址空间随机化,因此每次应用程序运行时,密钥都存储在不同的地址
  • 使用操作系统密钥库
  • 使用 C/C++ 等“硬”语言,而不是 Java 或 Python 等基于 VM 的内省语言

这样的方法当然聊胜于无,但熟练的黑客迟早会破解它。

代币

从理论的角度来看,身份验证是证明被挑战的人是他们所说的人的行为。传统上,这是通过共享秘密(密码)实现的,但还有其他方法可以证明自己,包括:

  • 带外身份验证。例如,在我居住的地方,当我尝试登录我的网上银行时,我会在手机上收到一次性密码(OTP) 作为短信。在这种方法中,我证明我拥有一个特定的电话号码
  • 安全令牌:要登录服务,我必须按下令牌上的按钮以获取 OTP,然后将其用作我的密码。
  • 其他设备:

    • 智能卡,特别是美国国防部使用的智能卡,它被称为CAC。Python 有一个名为pyscard的模块来与此接口
    • NFC设备

还有一个更完整的列表在这里

所有这些方法之间的共同点是最终用户控制这些设备,并且秘密实际上永远不会离开令牌/卡/电话,当然也永远不会存储在您的程序中。这使它们更加安全。

会话窃取

然而(总有一个然而):

让我们假设您设法保护登录,因此黑客无法访问安全令牌。现在您的应用程序正在愉快地与安全服务进行交互。不幸的是,如果黑客可以在您的计算机上运行任意可执行文件,则黑客可以劫持您的会话,例如通过在您对服务的有效使用中注入额外的命令。换句话说,虽然您已经保​​护了密码,但它完全无关紧要,因为黑客仍然可以访问“安全”资源。

这是一个非常真实的威胁,正如多次跨站点脚本攻击所显示的那样(一个例子是美国银行和美国银行网站易受攻击,但还有无数)。

安全代理

如上所述,将帐户凭据保存在第三方服务或系统上是一个基本问题,以便应用程序可以登录,尤其是在唯一的登录方法是用户名和密码的情况下。

一种方法是通过将与服务的通信委托给安全代理来部分缓解这种情况,并在应用程序和代理之间开发一种安全登录方法。在这种方法中

  • 应用程序使用 PKI 方案或双因素身份验证来登录安全代理
  • 用户将第三方系统的安全凭证添加到安全代理。凭据永远不会存储在应用程序中
  • 稍后,当应用程序需要访问第三方系统时,它会向代理发送请求。代理使用安全凭证登录并发出请求,将结果返回给应用程序。

这种方法的缺点是:

  • 用户可能不想信任存储凭据的安全代理
  • 用户可能不信任通过它流向第三方应用程序的数据的安全代理
  • 应用程序所有者有额外的基础设施和托管成本来运行代理

一些答案

所以,关于具体的答案:

如何使用 python 安全地存储身份验证凭据?

  • 如果存储应用程序的密码以验证用户,请使用 PBKDF2 算法,例如https://www.dlitz.net/software/python-pbkdf2/
  • 如果存储密码/安全令牌以访问其他服务,则没有绝对安全的方法。
  • 但是,请考虑使用例如pyscard将身份验证策略切换到例如智能卡。您可以使用智能卡对应用程序的用户进行身份验证,也可以使用 X.509 证书对另一个服务安全地对应用程序进行身份验证。

可以对“一切都是公共的”哲学做些什么吗?我知道“我们在这里都是同意的成年人”,但我们是否应该被迫在与攻击者共享密码和使用另一种语言之间做出选择?

恕我直言,用 Python 编写一个特定的模块并没有错,它确实隐藏了秘密信息,使其成为其他人重用的正确错误(惹恼其他程序员是它的目的)。您甚至可以在 C 中编写大部分代码并链接到它。但是,出于明显的原因,不要对其他模块执行此操作。

但是,最终,如果黑客控制了计算机,则计算机上根本就没有隐私。理论上最坏的情况是您的程序在虚拟机中运行,并且黑客可以完全访问计算机上的所有内存,包括 BIOS 和显卡,并且可以通过身份验证逐步了解您的应用程序以发现其秘密。

鉴于没有绝对的隐私,剩下的只是混淆,而保护级别仅仅是混淆的难度与熟练的黑客想要信息的程度。我们都知道这将如何结束,即使对于定制硬件价值数十亿美元的产品也是如此。

使用 Python 密钥环

虽然这将相对于其他应用程序非常安全地管理密钥,但所有 Python 应用程序都共享对令牌的访问权限。对于您担心的攻击类型,这一点也不安全。

于 2013-02-04T08:18:21.730 回答
2

我不是该领域的专家,我真的只是想解决与您相同的问题,但看起来像Hashicorp 的 Vault 之类的东西可能会提供很好的帮助。

特别是 WRT 存储第三部分服务凭证的问题。例如:

在 API 驱动的现代世界中,许多系统还支持以编程方式创建访问凭证。Vault 通过称为动态机密的功能利用这种支持:按需生成的机密,并且还支持自动撤销。

对于 Vault 0.1,Vault 支持动态生成 AWS、SQL 和 Consul 凭证。

更多链接:

于 2015-09-30T09:35:46.717 回答