Keystroke Deanonymization
Deanonymization using user keystrokes, keystroke deanonymization, keystroke fingerprinting and defenses.
Keystroke Dynamics[edit]
Keystroke biometric algorithms have advanced to the point where it is viable to fingerprint users based on soft biometric traits. This is a privacy risk because masking spatial information -- such as the IP address via Tor -- is insufficient to anonymize users. [1]
Users can be uniquely fingerprinted based on: [2]
- Typing speed.
- Exactly when each key is located and pressed (seek time), how long it is held down before release (hold time), and when the next key is pressed (flight time).
- How long the breaks/pauses are in typing.
- How many errors are made and the most common errors produced.
- How errors are corrected during the drafting of material.
- The type of local keyboard that is being used.
- Whether they are likely right or left-handed.
- Rapidity of letter sequencing indicating the user's likely native language.
- Keyboard Layout as the placement of the keys on the keyboard leads to different key seek times and typing mistakes.
A unique neural algorithm generates a primary pattern for future comparison. It is thought that most individuals produce keystrokes that are as unique as handwriting or signatures. This technique is imperfect; typing styles can vary during the day and between different days depending on the user's emotional state and energy level. [2]
Unless protective steps are taken to obfuscate the time intervals between key press and release events, it is likely most users can be deanonymized based on their keystroke manner and rhythm biometrics. Adversaries are likely to have samples of clearnet keystroke fingerprinting which they can compare with "anonymous" Tor samples.
Typing on the most popular keyboard layout which is probably en-US might help mitigation however a more effective way is the following. At a minimum users should not type into browsers with Javascript enabled, since this opens up this deanonymization vector. Text should be written in an offline text editor and then copied and pasted into the web interface when it is complete.
In addition, users must also disguise their linguistic style to combat stylometric analysis and be aware of mouse tracking techniques available to adversaries.
Defenses[edit]
Kloak[edit]
Kloak is an input device anonymization tool. It includes mitigations for keystroke fingerprinting as well as for masking unique user mouse movement behavior.[3][4][5]
- Non-Qubes-Whonix supported by default.
- Qubes-Whonix™ Unavailable. [6]
Kloak is installed in Non-Qubes-Whonix™ Whonix-Workstation™ by default.
We recommend installing kloak on the host too so it remains effective in event of a Whonix-Workstation VM compromise. If you need to access accounts (for example banking) that enforce keystroke biometrics, then it may be a good idea to just limit installation to Whonix VMs.
Kloak has the added benefit of foiling attacks that identify search queries in encrypted network traffic using information leaked through autocomplete suggestions of search engines. [7] [8]
Rescue Keys[edit]
Kloak by default recognizes a "rescue key" sequence, which will terminate the kloak process.
The default rescue key sequence is KEY_LEFTSHIFT + KEY_RIGHTSHIFT + KEY_ESC
(i.e. left shift + right shift + escape).
Depending on how kloak is run:
- A) daemon: If you are running kloak as a systemd service (the default), this will restart kloak (as systemd will automatically re-launch it after it terminates).
- B) manual: If you are running kloak in a terminal, this will terminate kloak, which then will be no longer anonymizing keyboard and mouse actions.
Rescue Keys Customization[edit]
Kloak rescue keys may be customized by using the -k
option, which takes a comma-separated list of key codes as an argument. The full list of supported key codes can be seen at keycodes.c
.
For instance, to run kloak with the rescue key set to KEY_LEFTSHIFT + KEY_ESC
, run:
1. Stop background kloak process first.
sudo systemctl stop kloak
2. Run kloak in terminal.
sudo kloak -k KEY_LEFTSHIFT,KEY_ESC
3. Terminate with Ctrl+C or rescue key sequence when done.
4. Restart background kloak process.
sudo systemctl start kloak
5. Persistent configuration change.
To make this change permanent, see setting persistent kloak settings.
6. Done.
Disabling rescue keys[edit]
Note: The disabling rescue keys feature is at time of writing only available from source code or in the testers repository.
Some users have reported that they are unable to use certain keyboard shortcuts on account of the rescue key functionality. To disable the rescue key feature entirely, you may use the -p
option. Be warned that this will prevent you from terminating or restarting kloak using the rescue key sequence! To run kloak with the rescue key feature disabled:
1. Stop background kloak process first.
sudo systemctl stop kloak
2. Run kloak in terminal.
sudo kloak -p
3. Terminate with Ctrl+C when done.
4. Restart background kloak process.
sudo systemctl start kloak
5. Persistent configuration change.
To make this change permanent, see setting persistent kloak settings.
6. Done.
Kloak Debug Mode[edit]
If you are experiencing problems with kloak, generating debug logs can be useful for determining what's going wrong.
Kloak provides a -v
option that is useful in these scenarios. Due to the volume of data kloak produces during logging, it is recommended that you run kloak in a terminal when gathering logs. To run kloak in verbose mode, run the following commands:
1. Stop background kloak process first
sudo systemctl stop kloak
2. Run kloak in terminal
sudo kloak -v
3. Gather logs, then terminate with Ctrl+C or rescue key sequence.
4. Restart background kloak process
sudo systemctl start kloak
5. Persistent configuration change.
To make this change permanent, see setting persistent kloak settings.
6. Done.
Setting persistent kloak settings[edit]
Notes:
- Kloak's verbose mode can be enabled as a persistent setting by following these instructions. However, verbose mode generates copious amounts of data, which may consume large amounts of disk space or cause wear-and-tear on the disks. Enabling verbose mode as a persistent setting is not recommended.
If you use kloak as a systemd service and wish to use some of its options, you may do so by adding a configuration file for kloak. To do this:
1. Open file /lib/systemd/system/kloak.service.d/50_user.conf
in an editor with root rights.
Non-Qubes-Whonix™
This box uses sudoedit
for better security.
sudoedit /lib/systemd/system/kloak.service.d/50_user.conf
Qubes-Whonix™
NOTES:
- When using Qubes-Whonix, this needs to be done inside the Template.
sudoedit /lib/systemd/system/kloak.service.d/50_user.conf
- After applying this change, shutdown the Template.
- All App Qubes based on the Template need to be restarted if they were already running.
- This is a general procedure required for Qubes and unspecific to Qubes-Whonix™.
Others and Alternatives
- This is just an example. Other tools could achieve the same goal.
- If this example does not work for you or if you are not using Whonix, please refer to this link.
sudoedit /lib/systemd/system/kloak.service.d/50_user.conf
2. Paste.
Note: Replace <options>
with the options you wish to pass to kloak.
[Service] ExecStart=/usr/sbin/kloak <options>
3. Save and exit.
4. Reload systemd manager configuration.
sudo systemctl daemon-reload
5. Restart kloak.
sudo systemctl restart kloak
6. Done.
Kloak will now run with custom options.
View kloak journal log[edit]
If you want to look at any info kloak may have output since starting it, you may do so by checking the journal logs. To do this, run:
sudo journalctl -u kloak | cat
xrdp[edit]
Looked into what would be necessary to make kloak work over xrdp. Sadly this does not seem possible, as xrdp acts as its own X server (to my awareness) and thus intercepting and delaying keystrokes would require kloak to somehow intercept the keystrokes at the layer between the X server and the applications. I looked ways of doing this but failed to find them - there are ways of logging keystrokes at the X server level, but my research failed to find a way to block keystrokes or otherwise keep them from being delivered to applications for the purpose of delaying them. This issue affects any use of kloak over a remote desktop session - unless the remote desktop application creates uinput devices on the remote machine and then feeds user input into them, kloak will not be able to intercept them.
Recommendation - xrdp users should run kloak on the client machine to obfuscate their typing patterns on the client. This will then naturally obfuscate them on the remote machine as well.
ArrayBolt3
Stop Kloak[edit]
It is usually not required to stop kloak unless for testing, debugging.
Stop clock until restart or reboot.
sudo systemctl stop kloak
Start Kloak[edit]
It is usually not required to start kloak as it is running by default.
Start kloak.
sudo systemctl restart kloak
Kloak Status[edit]
sudo systemctl status kloak
Defense Testing[edit]
You can test that kloak actually works by trying a keystroke test website. https://vmonaco.com/device-fingerprinting/ is a good choice as it is free, open source, and requires no personal data or signup process to use. The code is visible at https://github.com/vmonaco/device-fingerprinting.
To use the test:
- Ensure kloak is not running.
- Open the website.
- Move the mouse around and click on random locations on the page. You will see a graph labeled "mousemove" start to update. As the mouse moves, the graph should eventually show a few (oftentimes only one) orange-marked spikes that act as a fingerprint for your device.
- Click inside the text area and type for some amount of time. A graph labeled "keydown" should show one or more prominent orange-marked spikes after a bit of typing.
- Start kloak. then refresh the page.
- Move the mouse around again. The graph will act erratically and fail to obtain an orange-marked spike for very long.
- Click inside the text area and type for some amount of time. The graph should act erratically similar to the mouse graph.
- By default, the website uses
event.timeStamp
as a time source for fingerprint extraction. If desired, repeat the above steps with the other time sources (Date.now()
,performance.now()
, andWeb Worker
).
A device or biometric fingerprint can be obtained quickly and with high certainty when kloak is not used. The tests done with kloak enabled show that kloak obfuscated typing behavior, making it difficult to authenticate or identify a particular user.
Note that websites that observe typing behavior will likely see users running kloak as being distinctly different from other users (due to the randomized, unnatural typing rhythms and mouse movements). This is similar to how Tor users can be detected separately from internet users who do not use Tor, but telling individual Tor users from each other is very difficult. As more users use kloak, the anonymity set will increase.
Other potential tests (not recommended):
- https://www.typingdna.com/demo-sametext.html
- https://github.com/topics/keystroke-dynamics
- forum discussion
Previously KeyTrac was recommended for testing kloak. However, the KeyTrac demo is no longer available. When KeyTrac did exist, the following results were obtained by training and testing KeyTrac with and without kloak:
Train normal, test normal
trial 1: 94% accuracy identified
trial 2: 92% accuracy
trial 3: 94% ..
Train normal, test kloak
trial 1: 18%
trial 2: 15%
trial 3: 19%
Train kloak, test kloak
trial 1: 40%
trial 2: 42%
trial 3 36%
Without kloak users can be identified with very high certainty. The second set of tests show that kloak definitely obfuscates typing behavior, making it difficult to authenticate or identify a particular user. Third set: users running kloak may look "similar" to other users running kloak. That is, it might be possible to identify kloak users from non-kloak users. These results are similar to the results obtained using vmonaco's device fingerprinting test.
References:
- Mouse Fingerprinting
- https://github.com/vmonaco/keystroke-obfuscation
- https://github.com/vmonaco/keystroke-obfuscation/issues/1#issuecomment-268598887
- https://github.com/vmonaco/kloak
- https://github.com/vmonaco/kloak/issues/7#issuecomment-893817507
- https://twitter.com/Whonix/status/1111053743905226752
- https://t.co/QcKyLppZBr
- https://forums.whonix.org/t/current-state-of-kloak/5605
- https://phabricator.whonix.org/T583
- https://forums.whonix.org/t/device-fingerprinting-with-peripheral-timestamps-mouse-fingerprinting/12114
See Also[edit]
References[edit]
- ↑ https://github.com/vmonaco/keystroke-obfuscation
- ↑ 2.0 2.1 https://en.wikipedia.org/wiki/Keystroke_dynamics
- ↑ https://github.com/vmonaco/kloak/pull/38
- ↑ https://github.com/vmonaco/kloak/pull/50#issuecomment-1657250132
- ↑ https://arxiv.org/pdf/2101.09087.pdf
- ↑
For previous tickets on this issue, see this.
- https://github.com/QubesOS/qubes-issues/issues/2558
- https://github.com/QubesOS/qubes-issues/issues/1850
- Using
/dev/input/event0
in Qubes VMs will not work since not a keyboard device.
- ↑ Feasibility of a Keystroke Timing Attack on Search Engines with Autocomplete
- ↑ https://www.usenix.org/sites/default/files/conference/protected-files/sec19_slides_monaco.pdf
We believe security software like Whonix needs to remain open source and independent. Would you help sustain and grow the project? Learn more about our 12 year success story and maybe DONATE!