【问题标题】:Mark data as sensitive in python在python中将数据标记为敏感
【发布时间】:2010-11-02 05:34:46
【问题描述】:

我需要在内存中短时间存储用户密码。我怎样才能做到这一点,而又不会在核心转储或回溯中意外披露此类信息?有没有办法将一个值标记为“敏感”,这样它就不会被调试器保存在任何地方?

【问题讨论】:

标签: python security passwords coredump


【解决方案1】:

没有办法“标记为敏感”,但您可以加密内存中的数据并在需要使用时再次解密——这不是一个完美的解决方案,但我能想到的最好的解决方案。

【讨论】:

    【解决方案2】:
    • 与单独存储的一次性填充物进行异或操作
    • 始终存储加盐哈希而不是密码本身

    或者,如果您对转储非常偏执,请将唯一随机密钥存储在其他地方,例如i 一个不同的线程,在注册表中,在您的服务器上,等等。

    【讨论】:

      【解决方案3】:

      编辑

      我已经制定了一个使用 ctypes(反过来使用 C)将内存归零的解决方案。

      import sys
      import ctypes
      
      def zerome(string):
          location = id(string) + 20
          size     = sys.getsizeof(string) - 20
      
          memset =  ctypes.cdll.msvcrt.memset
          # For Linux, use the following. Change the 6 to whatever it is on your computer.
          # memset =  ctypes.CDLL("libc.so.6").memset
      
          print "Clearing 0x%08x size %i bytes" % (location, size)
      
          memset(location, 0, size)
      

      我不保证此代码的安全性。它经过测试可在 x86 和 CPython 2.6.2 上运行。更长的文章是here

      在 Python 中解密和加密将不起作用。字符串和整数是固定的和持久的,这意味着你会在各处留下一堆乱七八糟的密码信息。

      散列是标准答案,当然明文最终需要在某个地方进行处理。

      正确的解决方案是将敏感进程作为一个 C 模块来做。

      但是,如果您的记忆不断受到损害,我会重新考虑您的安全设置。

      【讨论】:

      • 这是对的。如果您/曾经/将密码读入 Python 对象,则它有可能被转储破坏。即使使用 C 也不是完美的(您仍然可以冻结程序并使用内核级调试器),但它应该已经足够好了。
      • 如果这与下面文章中提到的memset 相同,这也是不安全的。 viva64.com/en/b/0178owasp.org/index.php/Insecure_Compiler_Optimization
      • 丹尼:memset 是安全的。您链接到的文章是关于 C 编译器删除 memset 调用的。当我们从 Python 显式调用 memset 时,它会被调用。
      • @Barry Archive.org 再次来袭! Here is a backup of the writeup
      • 此解决方案在 Mac OS 10.8.5(使用memset=ctypes.CDLL("libc.dylib").memset)下使 Python 2.7.2(Segmentation fault:11)崩溃
      【解决方案4】:

      ... 唯一的解决方案是使用可变数据结构。 是,你必须只使用允许你动态的数据结构 替换元素。例如,在 Python 中,您可以使用列表来存储 字符数组。但是,每次添加或删除元素时 从列表中,该语言可能会在您背后复制整个列表, 取决于实施细节。为了安全起见,如果你必须 动态调整数据结构的大小,你应该创建一个新的,复制 数据,然后覆盖旧的。例如:

      def paranoid_add_character_to_list(ch, l):
        """Copy l, adding a new character, ch.  Erase l.  Return the result."""
        new_list = []
        for i in range(len(l)):
          new_list.append(0)
        new_list.append(ch)
        for i in range(len(l)):
          new_list[i] = l[i]
          l[i] = 0
        return new_list
      

      来源:http://www.ibm.com/developerworks/library/s-data.html

      • 作者:John Viega (viega@list.org) 是 Building Secure 的合著者 软件 (Addison-Wesley, 2001) 和 Java 企业架构 (O'Reilly and Associates, 2001)。 John 撰写了 50 多个 技术出版物,主要是在软件安全领域。 他还写了 Mailman,GNU 邮件列表管理器和 ITS4,一个工具 用于发现 C 和 C++ 代码中的安全漏洞。

      【讨论】:

      • 作为一种变体:使用这种技术填充 bytearray 会产生一个对象,该对象可以在许多 python 代码中用于代替 bytes 实例......并且可以等效之后清除。
      【解决方案5】:

      基于 culix 的回答:以下适用于 Linux 64 位架构。
      在基于 Debian 的系统上测试。

      import sys 
      import ctypes
      
      def nuke(var_to_nuke):
          strlen = len(var_to_nuke)
          offset = sys.getsizeof(var_to_nuke) - strlen - 1
          ctypes.memset(id(var_to_nuke) + offset, 0, strlen)
          del var_to_nuke               # derefrencing the pointer.
      

      【讨论】:

        猜你喜欢
        • 2019-12-16
        • 1970-01-01
        • 2022-07-08
        • 1970-01-01
        • 2018-08-15
        • 1970-01-01
        • 2017-07-25
        • 2017-09-05
        • 2020-02-01
        相关资源
        最近更新 更多