|
|
|
|
| |
This advisory demonstrates several weaknesses in implementations of SSH (Secure Shell) protocols. When exploited, they let the attacker obtain sensitive information by passively monitoring encrypted SSH sessions. The information can later be used to speed up brute-force attacks on passwords, including the initial login password and other passwords appearing in interactive SSH sessions, such as those used with su(1) and Cisco IOS "enable" passwords.
All attacks described in this advisory require the ability to monitor (sniff) network traffic between one or more SSH servers and clients. |
| |
Credit:
This advisory, and the unofficial SSH 1.2.x patch were written by Solar Designer and Dug Song. The authors would like to thank the SSH implementation authors, especially Markus Friedl and Theo de Raadt (of OpenSSH), Simon Tatham (PuTTY), and Niels Moller (LSH) for improving on our initial SSH traffic analysis countermeasures. We would also like to thank David Wagner and Dawn Xiaodong Song at the University of California, Berkeley and Ariel Futoransky of CORE-SDI for insightful discussions.
|
| |
Version 1 of the SSH protocol, unless its implementation takes special precautions to avoid this, exposes the exact lengths of login passwords used with password authentication. The SSH-2 protocol doesn't reveal as much information, but a range of possible password lengths can still be determined.
Additional weaknesses make it possible to detect when a password is entered during an interactive SSH session, and to discover even more information about such passwords, including their exact lengths (with both protocol versions) and timing information. The latter exposes the likelihood of possible characters in each position of a password.
All this information may be entered into a brute-force password cracker for a significant speedup due to reduced keyspace and other optimizations, including attacking user passwords in the order of increasing estimated complexity.
Additionally, our SSH traffic analysis tool is able to detect the use of RSA or DSA authentication, and in the case of RSA and SSH 1.2.x derived SSH server implementations, the number of authorized_keys file options. The latter is possible due to debugging packets sent by those implementations. If a SSH session with RSA authentication but no authorized_keys options is seen, an attacker may infer that the client machine has the private key sufficient to obtain full shell access to the server. If the session is automated, the private key has to be stored unencrypted.
Finally, it is possible to determine the lengths of shell commands, and in some cases, the commands themselves (from a small list of common ones) in an interactive session (which isn't a security issue under most circumstances).
It should be noted that, despite their simplicity, traffic analysis attacks such as those presented in this advisory haven't been well researched. We expect that similar attacks are possible against most other "secure" (encrypted) remote login protocols. We also expect additional traffic analysis attacks on SSH to be discovered. In particular, there may be recognizable patterns in X11 connections forwarded over SSH, but these are out of the scope of this advisory.
Password authentication vulnerability
When encapsulating plaintext data in a SSH protocol packet, the data is padded to the next 8-byte boundary (or whatever the cipher's block size is, with SSH-2), encrypted, and sent along with the plaintext length field. SSH-1 sends this field in the clear.
As a result, an attacker passively monitoring a SSH session is able to detect the amount of plaintext sent in each packet - exact for SSH-1, or a range of possible lengths for SSH-2.
Since the login password is sent in one SSH-1 protocol packet without any special precautions, an attacker can determine the exact password length.
With SSH-2, other information (including the username) is transmitted in the same packet and the plaintext length is encrypted, so only a range of possible password lengths can be determined.
Fortunately, due to the use of C strings in most SSH-1 server implementations, it is usually possible for a SSH client to add sufficient NUL padding for just the passwords without a change to the protocol. We recommend that future SSH-1 server implementations allow for this padding, even in cases where the underlying OS interfaces do not necessarily imply this.
An alternative workaround, proposed by Simon Tatham, is to send a sequence of SSH-1 messages containing strings of increasing length.
Exactly one of these messages is SSH_MSG_PASSWORD and contains the password string. All the rest are SSH_MSG_IGNORE. It is important that the number of messages sent remains constant and is sufficient to cover the longest password we expect to see. To safely transmit passwords of up to 32 characters, 1088 bytes of SSH-1 messages are needed, which may still fit within one TCP segment. This approach has the advantage that no assumption about SSH-1 server implementations is made (other than that they implement the protocol correctly; some implementations are known to have problems handling SSH_MSG_IGNORE).
The SSH-2 protocol allows for a solution (independently proposed by several SSH-2 implementation authors) with less overhead, and without reliance on artifacts of protocol implementation. A pair of SSH-2 messages, SSH_MSG_USERAUTH_REQUEST and SSH_MSG_IGNORE, may be constructed such that their combined length remains constant. The messages can then be sent to the transport layer at once.
Interactive session weaknesses
With interactive shell sessions, input characters are normally echoed by the remote end, which usually results in an echo packet from the server for each input character. However, if an application turns input echoing off, such as for entering a password, the packets start to go in one direction only - to the server. Our simple traffic analysis tool is able to detect this easily and reliably.
Once an attacker knows that the victim is entering a password, all they need to do is count the packets that didn't generate a reply packet from the server. In the case of SSH-1, the sum of plaintext sizes gives the exact password length, save any backspace characters. With SSH-2, the attacker has to assume that each packet contains only one password character, which is typically the case.
The delays between packets give the attacker additional information on the likelihood of possible characters in each position of the password. For example, if the delay before a character is larger than most other delays, it is likely that the character requires more than one keystroke to type.
When typing commands in a command-line shell over SSH, each character generates a tiny echo packet from the server. However, once the entire command is entered, a larger packet - containing the shell prompt and possibly the command's output - is sent by the server.
By counting the tiny packets (or the plaintext lengths in packets sent to the server, in the case of SSH-1), the attacker can infer the length of each shell command. To make detection more reliable with SSH-1, it is usually possible to detect backspaces by assuming that they produce a 3-character response (^H, space, ^H).
Once again, the delays may be used - this time for inferring the actual shell commands typed, from a small list of common ones.
The partial solution we propose is to modify SSH servers such that they simulate echo packets when terminal echo is disabled by an application. The SSH_MSG_IGNORE message type may be used to ensure the client doesn't actually process the contents of these fake packets.
Thus, no change to the protocol is required.
It is important to note that this partial solution may only defeat the most generic way to infer that a password is entered. In many cases it is possible to do the same by other means, including monitoring other related network traffic and events local to a SSH server system.
Solving traffic analysis vulnerabilities not related to password information would increase the protocol overhead significantly, and thus doesn't seem practical for many current uses of SSH.
Compression
The use of compression makes many of the traffic analysis attacks described above significantly less reliable. This is because the same amount of plaintext no longer results in the same amount of data being transmitted. The packet sizes are somewhat "randomized".
However, it is likely that compression also enables yet another class of traffic analysis attacks, as the changes to packet size due to compression aren't actually random - they depend on the plaintext packet contents.
We're already aware of one practical attack that is possible due to compression. With SSH-2, the SSH_MSG_USERAUTH_REQUEST message is transmitted after compression is negotiated. If enabled, the size of the resulting TCP segment will depend on the entropy of the plaintext password. If a SSH_MSG_IGNORE message is used to pad the password as we have proposed, compression may defeat some of the benefit this could have provided. This instance of the problem may be solved by transmitting the SSH_MSG_USERAUTH_REQUEST and SSH_MSG_IGNORE messages uncompressed. However, this is non-trivial to implement if a generic compression library is used.
Related work
Several of the attacks outlined in this advisory were also independently discovered by the authors of the following paper (still work-in-progress), which describes some of them in greater detail:
Dawn Xiaodong Song, David Wagner, Xuqing Tian:
``Timing Analysis of Keystrokes and Timing Attacks on SSH.''
In particular, they reveal that inter-keystroke timings leak about 1 bit of information per character pair, and describe an attacking system, Herbivore, which tries to learn users' passwords by monitoring SSH sessions. Herbivore is demonstrated to reduce the search space for uniformly randomly chosen passwords of 8 characters by a factor of 50.
Although the paper is not yet publicly available, vendors working to fix these problems may contact David Wagner or Dawn Xiaodong Song to obtain a copy.
Fixes
Several SSH implementations have been changed to include fixes which reduce the impact of some of the traffic analysis attacks described in this advisory. It is important to understand that these fixes are by no means a complete solution to traffic analysis - only simple remediation for the most pressing vulnerabilities described above.
OpenSSH:
Fixes have been initially applied to OpenSSH starting with version 2.5.0. OpenSSH 2.5.2 contains the more complete versions of the fixes and solves certain interoperability issues associated with the earlier versions.
PuTTY:
PuTTY 0.52 will include defenses against inferring length or entropy of initial login passwords, for both SSH-1 and SSH-2.
SSH 1.2.x:
SSH 1.2.x users can use this unofficial patch (the patch is against version 1.2.27, but applies to 1.2.31 as well). Please note that a SSH server with this patch applied will not interoperate with client
versions 1.2.18 through 1.2.22 (inclusive).
- --- ssh-1.2.27.orig/sshconnect.c Wed May 12 15:19:29 1999
+++ ssh-1.2.27/sshconnect.c Tue Feb 20 08:38:57 2001
@@ -1258,6 +1258,18 @@
fatal("write: %.100s", strerror(errno));
}
+void ssh_put_password(char *password)
+{
+ int size;
+ char *padded;
+
+ size = (strlen(password) + (1 + (32 - 1))) & ~(32 - 1);
+ strncpy(padded = xmalloc(size), password, size);
+ packet_put_string(padded, size);
+ memset(padded, 0, size);
+ xfree(padded);
+}
+
/* Starts a dialog with the server, and authenticates the current user on the
server. This does not need any extra privileges. The basic connection
to the server must already have been established before this is called.
@@ -1753,7 +1765,7 @@
/* Asks for password */
password = read_passphrase(pw->pw_uid, prompt, 0);
packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
- - packet_put_string(password, strlen(password));
+ ssh_put_password(password);
memset(password, 0, strlen(password));
xfree(password);
packet_send();
@@ -1791,7 +1803,7 @@
{
password = read_passphrase(pw->pw_uid, prompt, 0);
packet_start(SSH_CMSG_AUTH_PASSWORD);
- - packet_put_string(password, strlen(password));
+ ssh_put_password(password);
memset(password, 0, strlen(password));
xfree(password);
packet_send();
- --- ssh-1.2.27.orig/serverloop.c Wed May 12 15:19:28 1999
+++ ssh-1.2.27/serverloop.c Tue Feb 20 08:38:56 2001
@@ -522,6 +522,9 @@
void process_output(fd_set *writeset)
{
int len;
+#ifdef USING_TERMIOS
+ struct termios tio;
+#endif
/* Write buffered data to program stdin. */
if (fdin != -1 && FD_ISSET(fdin, writeset))
@@ -543,7 +546,18 @@
}
else
{
- - /* Successful write. Consume the data from the buffer. */
+ /* Successful write. */
+#ifdef USING_TERMIOS
+ if (tcgetattr(fdin, &tio) == 0 &&
+ !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
+ /* Simulate echo to reduce the impact of traffic analysis. */
+ packet_start(SSH_MSG_IGNORE);
+ memset(buffer_ptr(&stdin_buffer),
|
|
|
|
|