Password field security and information leaking

Albert Astals Cid aacid at kde.org
Sun Oct 14 17:08:57 BST 2018


El diumenge, 14 d’octubre de 2018, a les 11:19:17 CEST, Ivan Čukić va escriure:
> Hi all,
> 
> 
> We are using QLineEdit (and QML equivalent) all over KDE for passwords. This 
> is an issue for types of attacks that extract raw process memory because the 
> passwords can be leaked.
> 
> QLineEdit stores the current value as plain text in a QString. Which means 
> that while the password entry is shown in the screen, the password is stored 
> in memory for all to see (problem 1).
> 
> When the QLineEdit is destroyed, so is the QString. But, while the data buffer 
> is 'deleted', its contents remain in memory until some other dynamically 
> allocated object is created in the same memory space and overwrites the data - 
> this is because QString does not zero-out its buffer on destruction. This 
> means that the passwords remain in memory for much longer than needed (problem 
> 2).
> 
> Because of string reallocation on resizing, it is quite possible that, while 
> the user is typing the password, that the string will be resized/reallocated 
> at least once. This means that partial passwords (data from the buffer in the 
> string before reallocation which is not zeroed-out) will remain in memory 
> until something else overwrites them (problem 3).
> 
> All this memory can end up written to the hdd/ssd if the application is moved 
> to swap by the OS (problem 4).
> 
> Transporting passwords via DBus (KWallet) is the problem 5 (guessing there's 
> no need to explain this one in more detail).
> 
> 
> Potential solutions:
> 
> Problem 2 is easily solved in Qt by having QLineEdit zero-out the string data 
> on destruction if the line edit is used as a password entry. I've submitted a 
> patch for this [1]. Another additional change that can be applied to QLineEdit 
> is to call QString::reserve(50-or-something) when the line edit is used as a 
> password field to minimize the possibility of problem 3 occurring for most 
> use-cases.
> 
> Other problems are more difficult to solve. They need a custom component (from 
> what I can tell).
> 
> Namely, the least a proper password entry component could do is to use a 
> custom QString-like class which zeroes-out buffers before deleting them (on 
> reallocation and destruction), and which tells the OS that the value contents 
> should never be swapped. There is a class in QCA that can be used for this 
> (SecureArray, based on botan::SecureVector).
> 
> Having a password entry component that uses a secure buffer like SecureArray 
> would minimize the time the entered password is in memory to only while the 
> component is shown (problem 1).
> 
> The only remaining problems are 1 and 5.
> 
> Problem 1 can not be completely solved. If the password data is kept in memory 
> encrypted, the key for decryption needs to also be somewhere so that the 
> program can get the actual password instead of the encrypted version.
> 
> Still, it would be an improvement over the current situation because the 
> encryption password would be some random array of bytes, and the encrypted 
> passwords would appear as random arrays of bytes (when encryption is good, 
> encrypted data looks random). Which means that any attacks with the aim of 
> extracting the password data couldn't be based on text-processing - they would 
> need quite some effort of analyzing memory layout to find both the key and the 
> password in order to decrypt it.

Is this a problem at all? 
I mean, by default applications can't read other applications memory so the only one that can try this kind of attacks is the root user. 

If your system is compromised to the fact that root is evil you have lost already, surely root can install a key logger or something that will make it easy for her to snoop your passwords than having the grep the memory for them, no? (Well on X11 any application can install a keylogger but let's assume you're under Wayland :D)

> Now comes the most interesting part (IMO). which solves problem 5 and also 
> influences the previous issue of having the decryption key in memory.
> 
> We can use a stream cipher to encrypt the password in memory. This means that 
> the password characters can be encrypted one by one as the user types them in 
> - no need to have the whole password unencrypted in memory at any point in 
> time during password entry.
> 
> If we use public/private key encryption, where the password entry is in one 
> process, and the password usage is in another, only the password usage process 
> will be able to decrypt the password (and, again, there will be no need to the 
> whole password to be decrypted at once - just one character at a time can be 
> sufficient in many use-cases). This means that the attacker will need to have 
> either access to the memory spaces of both processes, or to hit a very narrow 
> window in the 'usage process' between 'I got the password' and 'I used the 
> password and zeroed-out the data'.
> 
> The pub/priv key exchange can be done mostly securely using Diffie-Hellman 
> protocol similar to what the Secret Service API [2] does. The only attack 
> vector would be to replace the normal dbus server with a malicious one. In 
> that case (having a malicious system component), I'd say the systems is 
> already compromised and that we can not do anything to protect the user.
> 
> 
> Thoughts?

AFAIR there's private dbus through apparmor, that'd be a simpler fix, unfortunately apparmor is not default on all distros so doesn't really solve much for us.

Not sure if any other dbus or kernel security enhacements implement or plan to implement this.

The problem i see with your implementation is that it secures the transport, but who cares about that? At this point i can just go to kwalletd and write a program that will say "Hey, I'm the network manager, give me this password" and there's no way for kwalletd to figure out if this is true or not, so it'll just give that program access to all my passwords without any need to snoop at the transport layer.

I've been thinking about that for a while and the only solution i've found is signing the binaries.

Cheers,
  Albert

> Cheers,
> Ivan
> 
> [1] https://codereview.qt-project.org/#/c/242202/
> [2] https://specifications.freedesktop.org/secret-service/index.html
> 
> 
> 
> dr Ivan Čukić
> KDE, ivan.cukic at kde.org, https://cukic.co/
> gpg key fingerprint: 8FE4 D32F 7061 EA9C 8232  07AE 01C6 CE2B FF04 1C12
> 
> 
> 






More information about the Kde-frameworks-devel mailing list