securely getting the user's password

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Mar 9 05:14:48 CET 2008


On Sat, 08 Mar 2008 18:50:30 -0800, Chick wrote:

> Hello,
> 
> I'm writing a security tool 

Oh good, just what we need, beginners writing security tools.


> which requies wiping off the memory of
> certain string after being used, which I've done by implementing it as a
> mutable list as follow:
> 
> class secureStr:

Unless you have a need for backwards compatibility, you probably should 
use new-style classes rather than classic classes.

>     def __init__(self, str):
>         self.__s = []
>         for i in range(len(str)):
>             self.s += str[i]
> 
>     def __str__(self):
>         return "".join(self.__s)
> 
>     def wipe(self):
>         for i in range(len(self.__s)):
>             self.s[i] = '\x00'
> 
>     def __del__(self):
>         self.wipe()

How do you prevent the operating system from paging the block of memory 
to disk? It's all well and good to wipe the password located at address 
0xb7f7a32c in RAM but that's not going to save you when the bad guys 
locate it in the swap file.


In any case, an easier way to get the above illusion of security is this:

class secureStr(list):
    def __str__(self):
        return "".join(self)
    def wipe(self):
        for i in xrange(len(self)):
            self[i] = '\x00'
    def __del__(self):
        self.wipe()

It contains the exact same security holes as your code, but is shorter.


> My question is how do I write a function to securely get the password
> from user (in text mode)? If I do sth like
> 
> import getpass
> securePass = secureStr(getpass,getpass())
> 
> doesn't that create an immediate string object that will stay in memory?

Yes, the string object will be deleted but not over-written. That may or 
may not happen. One way to increase the chances of that happening is:

import getpass
securePass = secureStr(getpass.getpass())  # not actually secure
s = '\00'*len(securePass)

It's not guaranteed to over-write the memory location with the 
intermediate string object, but you might get lucky.

What's the threat you're defending against? It seems to me that you are 
worrying about somebody (a person? another program? the operating 
system?) reading the password out of Python's free memory blocks. Fair 
enough, attackers can and have recovered passwords out of free memory.

But a far bigger security hole is that the password is sitting there in 
your securePass variable in plain text. What are you doing about that?


-- 
Steven



More information about the Python-list mailing list