Support for ping@openssh.com and keystroke timings obfuscation
LibSSH and pre-9.5 OpenSSH sends packets containing keystroke information to the server as soon as possible when users start typing in interactive mode on the client. A passive attacker, although he cannot see the content of the messages, can see when these have been sent and can use this information, for example, in finding password length or in more complicated ways, as outlined in this paper (which I haven't finished reading) about SSH specifically: www.cs.berkeley.edu/~daw/papers/ssh-use01.pdf (though only SSH v1) from 2001 and related LWN post from 2008: https://lwn.net/Articles/298833/. To curb this, OpenSSH has implemented a ping@openssh.com extension in version 9.5: An authenticated party (either client or server) can send a ping message to the other party at any time and expects an immediate pong message reply (except for during rekeying) which has a copy of the ping's data. The idea is that using this, the client can send pings at a fixed rate while the user is typing to confuse an eavesdropper, and then can add some random pings after the user has stopped typing so he won't know when the user's stopped, as explained in Damien Miller's commit:
CVSROOT: /cvs Module name: src Changes by: djm@cvs.openbsd.org 2023/08/27 21:31:16
Modified files: usr.bin/ssh : clientloop.c misc.c misc.h packet.c packet.h readconf.c readconf.h ssh_config.5
Log message: Add keystroke timing obfuscation to the client.
This attempts to hide inter-keystroke timings by sending interactive traffic at fixed intervals (default: every 20ms) when there is only a small amount of data being sent. It also sends fake "chaff" keystrokes for a random interval after the last real keystroke. These are controlled by a new ssh_config ObscureKeystrokeTiming keyword/
feedback/ok markus@
And here's the commit about pings:
CVSROOT: /cvs Module name: src Changes by: djm@cvs.openbsd.org 2023/08/27 21:28:43
Modified files: usr.bin/ssh : PROTOCOL kex.c kex.h packet.c ssh2.h
Log message: Introduce a transport-level ping facility
This adds a pair of SSH transport protocol messages SSH2_MSG_PING/PONG to implement a ping capability. These messages use numbers in the "local extensions" number space and are advertised using a " ping@openssh.com" ext-info message with a string version number of "0".
ok markus@
This cannot be done with other means as explained by Miller under "3. Motivation" in his RFC draft for the extension: "https://github.com/djmdjm/drafts/blob/master/draft-miller-ssh-ping.txt#L121" (which has recently expired. I don't know what that means). In brief, SSH_MSG_IGNORE won't work because there's no echo and SSH_MSG_GLOBAL_REQUEST's will be too large to be disguised as smaller packets. Some other relavant links are:
- PROTOCOL for OpenSSH 9.6: https://github.com/openssh/openssh-portable/blob/8241b9c0529228b4b86d88b1a6076fb9f97e4a99/PROTOCOL#L107
- Hackernews discussion: https://news.ycombinator.com/item?id=37307708
- LWN article about OpenSSH 9.5 release: https://lwn.net/Articles/946497/
About implementation, I think it should be simple enough to add ping support and will try to implement it soon. Then servers will be able to support the client's effort in timing obfuscation. The implementation of timing obfuscation on the client's side seems relatively straightforward as well. It also seems hard for this to cause security issues if we have bugs because of how separate it is from authentication etc. (though I have my methods... unfortunately. Naturally I do plan on testing everything properly of course). The worse that can happen seems like a network issue because the client accidentally sends too many packets.
Thoughts? Any mistakes/misunderstandings on my end? We do not need to replicate OpenSSH's method of sending pings, we could do it a different way if we'd like, or use it in other places as well to hide timing information other than just that of keystrokes. I don't have many ideas about that though.