Securely Erasing Password in Memory (Python)

Question:

How do you store a password entered by the user in memory and erase it securely after it is no longer need?

To elaborate, currently we have the following code:

username = raw_input('User name: ')
password = getpass.getpass()
mail = imaplib.IMAP4(MAIL_HOST)
mail.login(username, password)

After calling the login method, what do we need to do to fill the area of memory that contains password with garbled characters so that someone cannot recover the password by doing a core dump?

There is a similar question, however it is in Java and the solution uses character arrays:
How does one store password hashes securely in memory, when creating accounts?

Can this be done in Python?

Asked By: maxyfc

||

Answers:

EDIT: removed the bad advice…

You can also use arrays like the java example if you like, but just overwriting it should be enough.

http://docs.python.org/library/array.html

Answered By: Trey Stout

Store the password in a list, and if you just set the list to null, the memory of the array stored in the list is automatically freed.

Answered By: AlbertoPL

Python doesn’t have that low of a level of control over memory. Accept it, and move on. The best you can do is to del password after calling mail.login so that no references to the password string object remain. Any solution that purports to be able to do more than that is only giving you a false sense of security.

Python string objects are immutable; there’s no direct way to change the contents of a string after it is created. Even if you were able to somehow overwrite the contents of the string referred to by password (which is technically possible with stupid ctypes tricks), there would still be other copies of the password that have been created in various string operations:

  • by the getpass module when it strips the trailing newline off of the inputted password
  • by the imaplib module when it quotes the password and then creates the complete IMAP command before passing it off to the socket

You would somehow have to get references to all of those strings and overwrite their memory as well.

Answered By: Miles

If you don’t need the mail object to persist once you are done with it, I think your best bet is to perform the mailing work in a subprocess (see the subprocess module.) That way, when the subprocess dies, so goes your password.

Answered By: zdan

There actually -is- a way to securely erase strings in Python; use the memset C function, as per Mark data as sensitive in python

Edited to add, long after the post was made: here’s a deeper dive into string interning. There are some circumstances (primarily involving non-constant strings) where interning does not happen, making cleanup of the string value slightly more explicit, based on CPython reference counting GC. (Though still not a “scrubbing” / “sanitizing” cleanup.)

Answered By: amcgregor

This could be done using numpy chararray:

import numpy as np

username = raw_input('User name: ')
mail = imaplib.IMAP4(MAIL_HOST)
x = np.chararray((20,))
x[:] = list("{:<20}".format(raw_input('Password: ')))
mail.login(username, x.tobytes().strip())
x[:] = ''

You would have to determine the maximum size of password, but this should remove the data when it is overwritten.

Answered By: heplat

The correct solution is to use a bytearray() … which is mutable, and you can safely clear keys and sensitive material from RAM.

However, there are some libraries, notably the python "cryptography" library that prevent "bytearray" from being used. This is problematic… to some extent these cryptographic libraries should ensure that only mutable types be used for key material.

There is SecureString which is a pip module that allows you to fully remove a key from memory…(I refactored it a bit and called it SecureBytes). I wrote some unit tests that demonstrate that the key is fully removed.

But there is a big caveat: if someone’s password is "type", then the word "type" will get wiped from all of python… including in function definitions and object attributes.

In other words… mutating immutable types is a terrible idea, and unless you’re extremely careful, can immediately crash any running program.

The right solution is: never use immutable types for key material, passwords, etc. Anyone building a cryptographic library or routine like "getpass" should be working with a "bytearray" instead of python strings.

Answered By: Erik Aronesty
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.