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