Password field security and information leaking
Ivan Čukić
ivan.cukic at kde.org
Sun Oct 14 10:19:17 BST 2018
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.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