Отметьте данные как чувствительные в python

Мне нужно сохранить пароль пользователя в течение короткого периода времени в памяти. Как я могу это сделать, но не иметь такой информации, случайно обнаруженной в coredumps или tracebacks? Есть ли способ отметить значение как "чувствительное", поэтому оно не сохраняется нигде отладчиком?

Ответ 1

Edit

Я сделал решение, которое использует 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. Более длинная запись здесь.

Расшифровка и шифрование в Python не будут работать. Строки и целые числа являются интернированными и постоянными, что означает, что вы оставляете беспорядок информации о пароле повсюду.

Хеширование является стандартным ответом, хотя, конечно, в конечном итоге должен быть обработан простой текст.

Правильное решение - делать чувствительные процессы как модуль C.

Но если ваша память постоянно подвергается риску, я бы переосмыслил вашу настройку безопасности.

Ответ 2

... Единственным решением для этого является использование изменяемых структур данных. То есть вы должны использовать только структуры данных, которые позволяют динамически заменять элементы. Например, в 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

  • Автор: Джон Вига ([email protected]) является соавтором Building Secure Software (Addison-Wesley, 2001) и Java Enterprise Architecture (O'Reilly and Associates, 2001). Джон создал более 50 технических публикаций, прежде всего в области обеспечения безопасности программного обеспечения. Он также написал Mailman, диспетчер списков рассылки GNU и ITS4, инструмент для обнаружения уязвимостей безопасности в коде C и C++.

Ответ 3

Никакой способ "отметить как чувствительный", но вы можете зашифровать данные в памяти и снова расшифровать его, когда вам нужно его использовать, - не идеальное решение, но лучшее, что я могу придумать.

Ответ 4

  • XOR с одноразовой вкладкой, хранящейся отдельно
  • всегда хранит соленый хеш, а не сам пароль

или, если вы очень параноикны о дампах, храните уникальный случайный ключ в каком-то другом месте, например. я другой поток, в реестре, на вашем сервере и т.д.

Ответ 5

основанный на ответе "Куликс": следующее работает с 64-битной архитектурой Linux.
Протестировано на системах на основе 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.