3

我实际上编写了一个 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 以使密码始终有可能以纯文本形式存储的问题?

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

4

2 回答 2

4

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

除非您运行一些打开漏洞的 python 代码,否则解释器不会被破坏。基本上,只要您不使用pickle模块(可以将任意 python 代码加载到解释器中)或调用evalexec任意代码之类的东西,您就应该是安全的。

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

于 2012-08-04T15:21:24.437 回答
4

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

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

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

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

于 2012-08-04T15:50:07.557 回答