Мне нужно сохранить пароль пользователя в течение короткого периода времени в памяти. Как я могу это сделать, но не иметь такой информации, случайно обнаруженной в coredumps или tracebacks? Есть ли способ отметить значение как "чувствительное", поэтому оно не сохраняется нигде отладчиком?
Отметьте данные как чувствительные в python
Ответ 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.