安全擦除内存中的密码(Python)

max*_*yfc 44 python security passwords

如何将用户输入的密码存储在内存中,并在不再需要后将其安全擦除?

详细说明,目前我们有以下代码:

username = raw_input('User name: ')
password = getpass.getpass()
mail = imaplib.IMAP4(MAIL_HOST)
mail.login(username, password)
Run Code Online (Sandbox Code Playgroud)

在调用该login方法之后,我们需要做些什么来填充包含带有乱码的密码的内存区域,以便有人无法通过执行核心转储来恢复密码?

有一个类似的问题,但它是在Java中,解决方案使用字符数组: 在创建帐户时,如何在内存中安全地存储密码?

这可以用Python完成吗?

Mil*_*les 41

Python对内存的控制水平不高.接受它,继续前进.您可以做的最好的事情是del password在调用之后mail.login,不保留对密码字符串对象的引用.任何声称能够做到这一点的解决方案只会给你一种虚假的安全感.

Python字符串对象是不可变的; 在创建字符串后,没有直接的方法来更改字符串的内容.即使你能够以某种方式覆盖所引用的字符串的内容password(这在技术上可能使用愚蠢的ctypes技巧),仍然会有各种字符串操作中创建的密码的其他副本:

  • 当getpass模块从输入的密码中删除尾随换行符时
  • 由imaplib模块引用密码,然后在将其传递给套接字之前创建完整的IMAP命令

你会以某种方式获得对所有这些字符串的引用并覆盖它们的内存.

  • 更不用说操作系统将整个内存页面交换到磁盘的可能性,它可能会持续数月. (12认同)
  • 交换问题不是python特有的,但是这里是关于该部分的讨论:https://security.stackexchange.com/questions/29350/swap-file-may-contain-sensitive-data (3认同)

amc*_*gor 19

实际上有一种方法可以安全地擦除Python中的字符串; 使用memset C函数,根据Mark数据在python中敏感

在帖子发布很久之后编辑添加:这里是对字符串实习的深入研究.在某些情况下(主要涉及非常量字符串),其中不会发生实习,基于CPython引用计数GC,使字符串值的清理稍微更明确.(虽然仍然不是"擦洗"/"消毒"清理.)

  • 请注意,这取决于操作系统.Windows和Linux代码在链接的帖子中给出. (2认同)
  • 我发现这个回答“是否可能”的论点比公认的答案更好,非常愚蠢。正如你提到的,它完全破坏了解释器;此外,它不能与任何其他常规 Python 字符串功能或制作副本或临时值的库一起使用。它依赖于比常规 C 更弱的类型安全/警告/错误。所以你最好首先使用 C。我不会将其描述为“在 Python 中可能”。我也不高兴第一个答案是正确的,但不幸的是,它是正确的。 (2认同)

zda*_*dan 6

如果你完成它后不需要邮件对象继续存在,我认为最好的办法是在子进程中执行邮件工作(参见子进程模块.)这样,当子进程死掉时,你的密码.


Eri*_*sty 5

正确的解决方案是使用 bytearray() ...它是可变的,您可以安全地从 RAM 中清除密钥和敏感材料。

然而,有一些库,特别是 python“加密”库,阻止使用“bytearray”。这是有问题的......在某种程度上,这些密码库应该确保只有可变类型用于密钥材料。

SecureString,它是一个 pip 模块,允许您从内存中完全删除密钥...(我对其进行了一些重构,并将其称为SecureBytes)。我编写了一些单元测试来证明密钥已完全删除。

但有一个很大的警告:如果某人的密码是“type”,那么“type”一词将从所有Python中删除......包括在函数定义和对象属性中。

换句话说......改变不可变类型是一个糟糕的主意,除非你非常小心,否则可能会立即使任何正在运行的程序崩溃。

正确的解决方案是:永远不要对密钥材料、密码等使用不可变类型。任何构建加密库或例程(如“getpass”)的人都应该使用“bytearray”而不是 python 字符串。