【问题标题】:Prevent a plain text password in RAM (Python)防止 RAM 中的纯文本密码 (Python)
【发布时间】:2012-08-02 07:49:00
【问题描述】:

我实际上编写了一个 Python 模块来访问 KeePass/KeePassX 数据库。我的问题是数据库的密码以纯文本形式保存在我的数据库对象中:

def __init__(self, filepath=None, masterkey=None, read_only=False,
             new = False):
    """ Initialize a new or an existing database.

    If a 'filepath' and a 'masterkey' is passed 'load' will try to open
    a database. If 'True' is passed to 'read_only' the database will open
    read-only. It's also possible to create a new one, just pass 'True' to
    new. This will be ignored if a filepath and a masterkey is given this
    will be ignored.

    """

    self.groups = []
    self.read_only = read_only
    self.filepath = filepath
    self.masterkey = masterkey # I mean this

我不知道如何避免这种情况。我唯一的想法是存储使用随机生成的密钥加密的密码(就像 KeePassX 所做的那样),但是 Python 不允许私有成员是否存在问题?我的意思是可以从正在运行的程序外部访问随机生成的密钥吗?或者是从 RAM 中转储程序内存的唯一可能性?如果后者的答案是“是”,那么应该是提高安全性还是我被误导了?

无论哪种方式,是否存在 Python 将字符串“抛出”到整个 RAM 以使密码始终有可能以纯文本形式存储的问题?

我知道有很多问题,但这是该项目中最关键的安全点之一。

【问题讨论】:

  • 无论何时将任何内容加载到内存中,即使是很短的时间,也总会有一个时刻可以转储内存并读出您的密钥。
  • 你为什么要存储密码?大多数系统只存储一个哈希值,因此即使在数据库受损的情况下,黑客也不会找出人们的密码,除非他们很短。
  • 这不是 KeePassX 的工作方式:它获取密钥,对其进行 n 次散列,添加一个随机字节字符串,然后再次对其进行散列。这是加密和解密的最终密钥。

标签: python security encryption


【解决方案1】:

Python 只能在解释器内部进行自省;因此,如果您担心读取密码的任何内容,则某些内容要么必须获得对解释器的访问权限,要么必须以某种方式转储进程内存。

除非您运行一些打开漏洞的 python 代码,否则解释器不会被破坏。基本上,只要你不使用pickle module(可以load arbitrary python code into the interpreter)之类的东西,或者在任意代码上调用evalexec,你应该是安全的。

当然,您无法避免将主密钥存储在内存中,即使只是很短的时间。您可以将存储的主密钥限制到您需要它的那一刻,然后通过分配None 或其他方式来擦除变量。

【讨论】:

  • 由于 GC,擦除变量不一定有帮助。如果攻击者可以在任意点倾倒您的 RAM,那么您也无能为力。
  • @Antimony:但我的观点是,该变量将不再可用于自省。
  • @Martijn:也就是说,加密密钥不会增加安全性?
  • @lykaner: 谁来加密密钥,密钥在使用前需要解密吗?如果您需要在使用前解密,您将在内存中保存明文,然后您又回到了原点。如果您必须加密密钥,那么您将在内存中拥有明文,您好,再一次!操作系统保护您的进程内存,所以我不会担心,因此加密密钥不会添加任何内容。
  • 如果攻击者能够长期访问您的系统并能够转储 RAM,那么除了公钥加密之外,任何事情都无济于事。
【解决方案2】:

如果您的操作系统具有进程内存保护(所有现代操作系统都具有此功能),那么在同一进程中运行的任何代码都可以访问密码。除非您授予以操作系统特定方式对内存页面的特定访问权限,否则其他进程将无法访问数据:这是 RPG 完成的一种方法。内核可以访问您的内存,从而访问密码,但是如果攻击向量通过该路径,您将遇到一些严重的问题。

如果您的操作系统具有虚拟内存,则包含密码的页面可能会写入 root 用户可以访问的文件。因此,在 root 中运行的进程可以从那里读取密码。但是,如果您有一个以 root 身份运行的恶意进程,您需要担心的问题会更严重。

对象中的私有成员是一种语言级别的保护,仅在编译或解释代码时强制执行。它对数据的RAM访问没有影响。

总之,密码在运行过程中是安全的。您只需要关心密码是否已保存到您控制的文件中或以某种方式写入您控制的流中。

【讨论】:

    猜你喜欢
    • 2012-12-31
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 2016-07-30
    • 2013-06-21
    相关资源
    最近更新 更多