Summary: |
RFE: systemd-ask-password should implement keyboard randomisation as a countermeasure to keyloggers |
Product: |
systemd
|
Reporter: |
Christoph Anton Mitterer <calestyo> |
Component: |
general | Assignee: |
systemd-bugs |
Status: |
NEW
---
|
QA Contact: |
systemd-bugs |
Severity: |
enhancement
|
|
|
Priority: |
medium
|
|
|
Version: |
unspecified | |
|
Hardware: |
All | |
|
OS: |
All | |
|
Whiteboard: |
|
i915 platform:
|
|
i915 features:
|
|
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.
Hey. A nice feature for systemd-ask-password would be a trivial but effective measure against keyloggers. The applications should randomly permute the mapping of keys every time a password is queried and display the mapping from the characters/keys, pressed on the input device, to those which are actually used in the password. An example would be this. > Key mappings: > character used for the password: ABCDEF0123456789$/; > character pressed on the device: ;E48AD05F29$7C/61B3 > Please enter your passpharse: Of course one would need to extend this to all usable characters. Pheraps the number of valid input characters should be configurable, i.e. that the user specifies which keyboardlayout is used and the valid characters are automatically deduced from that and/or that the user can give a textfile, which simply contains all the valid passphrase characters. Further, the randomisation MUST take place each time the passphrase is requested, so it should not only happen once per session or once the system boots,... and especially it should also happen on each retry! If not, it might again be possible for an attacker that has a keylogger in place to make statistical attacks. And it should be asserted, that only high quality entropy is used for the randomisation, especially since much of these password queries may happen during boot (e.g. dm-crypt) and urandom may not yet be well enough sed. If /dev/random blocks, than ask-password should really print a message that the user should generate entropy, just as e.g. gnupg does during key generation. Now what's the benefit from all this? Even if an attacker has a hardware (or software) keylogger in place, he won't know the random mapping of the keys. So he only logs the length of the password and the statistical distribution of the keys - if the password is well enough, the latter shouldn't matter and there isn't much that can be done against the former[0]. This is especially handy in scenarios like this: Using a gpg encrypted key for dm-crypt/LUKS. If the attacker can log the passphrase, it's useless to him since a) it's randomised and b) he doesn't automatically have the gpg-encrypted key. And even if he get's the gpg-encrypted key, he still only has a passphrase which was valid only once for that specific mapping. The downside is of course, that it takes longer for a user to enter his passphrase, but since the whole thing should be just optional, it doesn't really matter. [0] Well there is one way around that, which could be implemented as a further option: To ignore any additional characters at the end of the passphrase, e.g. if we have the mappings from the example from above, and the real password would be: AFFE123 the user would need to enter: ;DDA5F2 but could also enter ;DDA5F2ajdk or ;DDA5F2sijk2jrlsdf or ;DDA5F2394573021xkkglAlf The downside of course is, that either systemd-ask-password would need to know the correct length of the passphrase in order to throw away the rest, or that the program where it feeds the passphrase into (and which knows the passphrase), also supports ignoring the extra characters. In practise though, many programs work with hashed passphrases, so the correct length would need to be given. This may be done in a separate random mapping step though, e.g. actual: 0123456789_ key: 4_860392157 Enter the password length: A user could now enter something like: 272735 ask-password should only take everything up to excluding the first occurrence of "_" (which is the key 2 in the above mapping) as the real length, so in the above example 2 would map to 7 7 would already be the first "_" and everything afterwards is ignored. So the length of the password would be 7 (which is just the length of the above "AFFE123". The trick with the additional 72734 and the "ignore everything after the first _" is to prevent that the attacker can find out how many digits the length of the passphrase has. With: 2 alone, he'd know that the length is something between [0; 9], which may already help a lot in brute force or statistical attacks But with 272735 he only knows that the length is something between [0; 999999], which doesn't really help anymore. Cheers, Chris.