Previous Page
Next Page

7.3. The SSHv2 Protocol

In this section, we explore the version 2 SSH protocol. SSHv2 adds features and deals with security problems in SSHv1, but the design is considerably different and more flexible.

At the time of this writing, SSHv2 is still in the RFC draft stage, so in one sense the protocol is not completely defined. On the other hand, SSHv2 is widely deployed by several vendors, so few substantive changes are likely to the base protocol as it now exists. The latest draft documents are available from the IETF SECSH working group at its Web site.

From an architectural standpoint, SSHv2 replaces the monolithic protocol of SSHv1 with a layered set of protocols, as shown in Figure 7.25. The SSHv2 transport protocol uses TCP to carry its messages. The SSHv2 authentication and connection protocols, in turn, use the SSHv2 transport protocol to carry their messages. We will look at each of these protocols in detail.

Figure 7.25. The SSHv2 Protocols Layered on the TCP/IP Stack


The SSHv2 Transport Protocol

The SSHv2 transport protocol provides a reliable, secure, full-duplex data stream between the SSH peers. Secure means that the data is encrypted and has strong integrity checking in place. Full duplex means that there is an independent data stream in each direction, so both sides can transmit data independently.

In addition to providing a secure data stream, the transport protocol is responsible for authenticating the server to the client; for negotiating the encryption, integrity, and compression methods; and for the initial and subsequent key exchanges. These methods can be negotiated independently for each side. Thus, each peer can choose its own encryption, integrity, and compression methods from the set supported by its peer.

The currently supported encryption methods are 3des-cbc; blowfish-cbc; 128, 192, and 256-bit twofish-cbc; 128, 192, and 256-bit aes-cbc; 128, 192, and 256-bit serpent-cbc; idea-cbc; 128-bit cast-cbc; and RC4. The only required method is 3des-cbc. The 128-bit aes-cbc method is recommended, and the others are optional. Notice that all the block ciphers operate in cipher block chaining mode.

The draft RFC on the SSHv2 transport protocol defines four possible MAC methods: SHA-1 HMAC, SHA-1 HMAC-96, MD5 HMAC, and MD5 HMAC-96. The SHA-1 HMAC-96 and MD5 HMAC-96 methods merely use the first 96 bits of the corresponding HMAC output. See Chapter 12 for more on SHA-1 HMAC-96 and MD5 HMAC-96. Only SHA-1 HMAC is required. SHA-1 HMAC-96 is recommended, and the MD5 methods are optional. Regardless of the method chosen, the MAC is calculated by

MAC = M(key, sequence number || m)

where M is the MAC method, key is computed from a shared secret, m is the unencrypted message, and sequence number is a 4-byte unsigned integer that has an initial value of 0 and is incremented by 1 after each packet is sent. The sequence number field is implicitit is never sent. The message, m, includes the length, type, and payload.

Currently, the only compression method defined is ZLIB. This is the same compression used in SSHv1, and as in SSHv1, it may be indicated when SSH is used over low-bandwidth connections.

As we'll see when we examine algorithm negotiation, the encryption, integrity, and compression methods are identified by symbolic names. This makes it easy to add new algorithms without changing the protocol itself. In addition, the naming conventions make it possible for individual users or groups to define their own algorithms and name them without fear of a naming collision.

Before discussing the SSHv2 transport protocol in detail, we need to understand the binary packet protocol that it uses. The packet layout is slightly different from the SSHv1 binary packet layout in Figure 7.2. The SSHv2 binary packet layout is shown in Figure 7.26.

Figure 7.26. The SSHv2 Binary Packet


The length field is the length of the entire packet, with the exception of the length and MAC fields. Similarly, the pad len field is the length of the padding field that follows the payload data.

The data field is the payload: the SSHv2 message that the transport layer is carrying. This message can be from any of the layers. The data field is length - pad len - 1 bytes long. As with the SSHv1 binary packet protocol, each message begins with a 1-byte message type. The message types used by the transport protocol are shown in Figure 7.27. In addition, message numbers 3049 are reserved for key-exchange packets. We will encounter these message types when we examine the key exchange protocols.

Figure 7.27. SSHv2 Transport Message Types

No.

MessageName

Message

1

SSH_MSG_DISCONNECT

terminate the connection

2

SSH_MSG_IGNORE

no op

3

SSH_MSG_UNIMPLEMENTED

message type not implemented

4

SSH_MSG_DEBUG

message contains debugging information

5

SSH_MSG_SERVICE_REQUEST

client service request

6

SSH_MSG_SERVICE_ACCEPT

server accepts service request

20

SSH_MSG_KEXINIT

algorithm negotiation

21

SSH_MSG_NEWKEYS

begin using new encryption keys


Immediately following the data is the padding field, which consists of pad len bytes of random data such that the length of the packet minus the MAC is a multiple of the cipher block size or 8, whichever is larger. The amount of padding must be between 4 and 255 bytes inclusive.

As discussed previously, the MAC field provides strong data integrity. Its length depends on the MAC method in use.

As we see from the figure, the entire packet, with the exception of the MAC, is encrypted. Note that this is different from the SSHv1 binary protocol, in which the CRC but not the length was encrypted.

Algorithm Negotiation and Key Exchange

The first step in establishing the transport layer's secure data stream is for the peers to agree on the encryption, integrity, and compression algorithms to use and to agree on the keys and IVs for the encryption and integrity algorithms. Figure 7.28 shows the protocol flow for this step. The process begins with the exchange of SSH_MSG_KEXINIT messages that list the methods that each peer can support and which methods each peer prefers. After each side receives its peer's SSH_MSG_KEXINIT message, the peers will either agree on the algorithms to use or send an SSH_MSG_DISCONNECT message and terminate the connection.

Figure 7.28. Algorithm Negotiation and Key Exchange


Currently, only two key-exchange methods are defined: Diffie-Hellman group 1 SHA-1 and Diffie-Hellman group exchange SHA-1 (DHGEX). The Diffie-Hellman group 1 SHA-1 protocol uses a fixed group with which to make its calculations, whereas the Diffie-Hellman group exchange SHA-1 protocol negotiates the group to use, based on the desired size of the prime modulus (see Chapter 3).

In Figure 7.28, the peers have agreed to use the Diffie-Hellman group exchange SHA-1 protocol. They begin by deciding on the group to use and then perform the Diffie-Hellman exchange. We will study these messages in detail shortly.

Finally, the client sends an SSH_MSG_NEWKEYS message to the server. This message signals that the peers should begin using the previously agreed on encryption, integrity, and compression algorithms. As we'll discuss later, either peer may initiate a new key exchange at any time. After the negotiation, one peer will send the SSH_MSG_NEWKEYS message to start the use of the new keys. The format of the SSH_MSG_KEXINIT message is shown in Figure 7.29.

Figure 7.29. The SSH_MSG_KEXINIT Message


The type field contains the message number: SSH_MSG_KEXINIT, in this case. The cookie field is not really a cookie, in the sense that the receiver will return it to the sender, but is simply a sequence of 16 random bytes. Because this field will be used in the key-generation process and because each side sends an independent value for this field, the cookie serves to ensure that neither side can completely determine the keys that the connection will use.

The next eight fields are lists of comma-separated algorithms that the sender supports. The lists are sorted in order of preference. We will see an example of these lists shortly. Most of these fields are self-explanatory. The host key algorithm field lists the types of host keys used for server authentication that the sender supports. Recall that in SSHv1, this was always an RSA key. SSHv2 supports additional methods.

The next two fields are lists of comma-separated language tags. The use of these tags is explained in RFC 3066 [Alvestrand 2001]. These lists are empty unless they are known to be needed by the sending party.

The kex field is a Boolean field that indicates whether a guessed key-exchange packet follows. The SSHv2 transport protocol allows each peer to guess what key-exchange protocol its peer will request and to send the initial key-exchange message immediately. If a guessed initial key-exchange packet follows, this field will be TRUE.

This capability adds complexity for little apparent benefitnever a good tradeoff in security software. OpenSSH always sets the kex field to FALSE but does, of course, honor its use by a peer.

Because no encryption is used until after the first SSH_MSG_NEWKEYS message, we can capture the entire algorithm and key-exchange protocol exchange of Figure 7.28. Here is a capture of an SSH_MSG_KEXINIT message:

1    15:12:17.920079 localhost.32775 > localhost.ssh: P 23:567(544)
     ack 24 win 32767 <nop,nop,timestamp 2036746 2036746> (DF)
1.1     4500 0254 001b 4000 4006 3a87 7f00 0001     E..T..@.@.:.....
1.2     7f00 0001 8007 0016 fded 9b30 fdd3 3e71     ...........0..>q
1.3     8018 7fff 2456 0000 0101 080a 001f 140a     ....$V..........
1.4     001f 140a 0000 021c 0914 752b cb0f 1554     ..........u+...T
1.5     933c a4d0 c8d9 f222 cbbb 0000 003d 6469     .<.....".....=di
1.6     6666 6965 2d68 656c 6c6d 616e 2d67 726f     ffie-hellman-gro
1.7     7570 2d65 7863 6861 6e67 652d 7368 6131     up-exchange-sha1
1.8     2c64 6966 6669 652d 6865 6c6c 6d61 6e2d     ,diffie-hellman-
1.9     6772 6f75 7031 2d73 6861 3100 0000 0f73     group1-sha1....s
1.10    7368 2d72 7361 2c73 7368 2d64 7373 0000     sh-rsa,ssh-dss..
1.11    0066 6165 7331 3238 2d63 6263 2c33 6465     .faes128-cbc,3de
1.12    732d 6362 632c 626c 6f77 6669 7368 2d63     s-cbc,blowfish-c
1.13    6263 2c63 6173 7431 3238 2d63 6263 2c61     bc,cast128-cbc,a
1.14    7263 666f 7572 2c61 6573 3139 322d 6362     rcfour,aes192-cb
1.15    632c 6165 7332 3536 2d63 6263 2c72 696a     c,aes256-cbc,rij
1.16    6e64 6165 6c2d 6362 6340 6c79 7361 746f     ndael-cbc@lysato
1.17    722e 6c69 752e 7365 0000 0066 6165 7331     r.liu.se...faes1
1.18    3238 2d63 6263 2c33 6465 732d 6362 632c     28-cbc,3des-cbc,
1.19    626c 6f77 6669 7368 2d63 6263 2c63 6173     blowfish-cbc,cas
1.20    7431 3238 2d63 6263 2c61 7263 666f 7572     t128-cbc,arcfour
1.21    2c61 6573 3139 322d 6362 632c 6165 7332     ,aes192-cbc,aes2
1.22    3536 2d63 6263 2c72 696a 6e64 6165 6c2d     56-cbc,rijndael-
1.23    6362 6340 6c79 7361 746f 722e 6c69 752e     cbc@lysator.liu.
1.24    7365 0000 0055 686d 6163 2d6d 6435 2c68     se...Uhmac-md5,h
1.25    6d61 632d 7368 6131 2c68 6d61 632d 7269     mac-sha1,hmac-ri
1.26    7065 6d64 3136 302c 686d 6163 2d72 6970     pemd160,hmac-rip
1.27    656d 6431 3630 406f 7065 6e73 7368 2e63     emd160@openssh.c
1.28    6f6d 2c68 6d61 632d 7368 6131 2d39 362c     om,hmac-sha1-96,
1.29    686d 6163 2d6d 6435 2d39 3600 0000 5568     hmac-md5-96...Uh
1.30    6d61 632d 6d64 352c 686d 6163 2d73 6861     mac-md5,hmac-sha
1.31    312c 686d 6163 2d72 6970 656d 6431 3630     1,hmac-ripemd160
1.32    2c68 6d61 632d 7269 7065 6d64 3136 3040     ,hmac-ripemd160@
1.33    6f70 656e 7373 682e 636f 6d2c 686d 6163     openssh.com,hmac
1.34    2d73 6861 312d 3936 2c68 6d61 632d 6d64     -sha1-96,hmac-md
1.35    352d 3936 0000 0009 6e6f 6e65 2c7a 6c69     5-96....none,zli
1.36    6200 0000 096e 6f6e 652c 7a6c 6962 0000     b....none,zlib..
1.37    0000 0000 0000 0000 0000 0000 0000 0000     ................
1.38    0000 0000                                   ....

On line 1.4 the length, pad len, and type fields are set in boldface. The length field is 540 (0x21c) bytes, which agrees with the total TCP segment length of 544 on line 1. Next is the pad len field, set to 9. The padding is the last 9 bytes of zeros in the packet; there is no MAC field yetthat field will be present after the SSH_MSG_NEWKEYS message. Finally, the message type is 20 (0x14), as expected.

The 16 bytes following the message type are the cookie. The lists of algorithms follow the cookie. For example, the list of key-exchange algorithms is on lines 1.51.9. We see that OpenSSH supports the diffie-hellman-group-exchange-sha1 and diffie-hellmangroup1-sha1 methods, as we discussed previously.

On lines 1.26 and 1.27 is an example of a "private algorithm." The MAC method hmac-ripemd160@openssh.com is defined by the OpenSSH organization. The @openssh.com identifies the method name space as belonging to the openssh.com domain. Other examples of private algorithms are found in the lists of encryption algorithmssee lines 1.151.17, for instance. Peers that don't know about these private methods will, of course, ignore them in the method-selection process. Methods assigned by IETF do not have the @ and domain name appended.

SSHv2 Diffie-Hellman Key Exchange Protocol

Returning to Figure 7.28, we see that the peers have agreed to use the Diffie-Hellman group exchange protocol for key exchange. The process begins with the client sending the server an SSH_MSG_KEXDH_GEX_REQUEST message, which specifies the maximum, minimum, and preferred prime size for the Diffie-Hellman group. The format of this message is shown in Figure 7.30. The type field is set to 34, indicating an SSH_MSG_KEXDH_REQUEST message. The min, preferred, and max fields are 32-bit unsigned integers specifying the minimum, preferred, and maximum size in bits of the prime for the group.

Figure 7.30. The SSH_MSG_KEXDH_REQUEST Message


The server selects a group of the appropriate size and informs the client of its choice with an SSH_MSG_KEXDH_GEX_GROUP message. This message (type 31) contains two multiprecision integers containing the chosen prime, p, and the corresponding generator g. After the client receives this message, both peers know the Diffie-Hellman group to use.

The next two messages complete the Diffie-Hellman key exchange. The client chooses a random number rC such that 1 < rC < (p - 1)/2, calculates e = grC mod p, and sends it to the server as a multiprecision integer in an SSH_MSG_KEXDH_GEX_INIT (type 32) message.

On receipt of the SSH_MSG_KEXDH_GEX_INIT message, the server chooses its own random number rS, calculates f = grS mod p, and sends this value along with its server key and the signature of the exchange hash, H, to the client in an SSH_MSG_KEXDH_GEX_REPLY message (Figure 7.31). We discuss the exchange hash shortly.

Figure 7.31. The SSH_MSG_KEXDH_GEX_REPLY Message


The SSH_MSG_KEXDH_GEX_REPLY message serves two purposes. First, it provides the client with its part of the Diffie-Hellman calculation that both peers will use to derive a shared secret. This is the value f . As we saw in Chapter 3, the client calculates K = frC, and the server calculates the same value independently as K = erS.

Second, the message provides server authentication. By including the host key, the message allows the client to identify the server from its database of server keys. Thesignature of the exchange hash, H, allows the client to verify that the server possesses the private key corresponding to the public key in the message.

The Exchange Hash

We've already seen that the exchange hash plays a role in server authentication. The exchange hash also plays an important role in key generation and the prevention of replay attacks. Finally, the initial exchange hashthe one from the first key exchangeserves as the session ID.

Recall that the key-exchange algorithms include a hash method. In both of the currently defined key-exchange methods, this is the SHA-1 hash. In what follows, we'll call this hash function h(m).

The exchange hash is calculated as

H = h(S)

where S is the concatenation of the quantities shown in Figure 7.32.

Figure 7.32. Quantities in the Exchange Hash

Type

Value

Explanation

DHGEX Only

string

VC

client's version string (CR and NL excluded)

 

string

VS

server's version string (CR and NL excluded)

 

string

IC

payload of client's SSH_MSG_KEXINIT message

 

string

IS

payload of server's SSH_MSG_KEXINIT message

 

string

KS

host key

 

integer

min

minimum group size

integer

n

preferred group size

integer

max

maximum group size

multiprec. int.

p

prime

multiprec. int.

e

client's Diffie-Hellman calculation

 

multiprec. int.

f

server's Diffie-Hellman calculation

 

multiprec. int.

K

shared secret

 


Note that the quantities that make up the exchange hash are available to both the client and server. This fact allows the client to verify the server's signature of the exchange hash and both sides to independently generate the session keys.

Before leaving our discussion of key exchange, let's turn to the other method: Diffie-Hellman group 1 with SHA-1. The method is similar to Diffie-Hellman group exchange but uses a fixed group, so there is no group-size negotiation.

Using a single fixed group, as this method does, leaves the Diffie-Hellman exchange open to a precomputation attack. Most of the work involved in solving the discrete logarithm problem involves precomputation on the group and its generator defined by the values of g and p [Herzog 1999]. Using a fixed group makes it possible to perform these computations once offline and then use them repeatedly in different attacks.

It uses just two messages: the SSH_MSG_KEXDH_INIT (type 30) message, which is identical to the SSH_MSG_KEXDH_GEX_INIT message from the group exchange method, and the SSH_MSG_KEXDH_REPLY (type 31) message, which is identical to the SSH_MSG_KEXDH_GEX_REPLY message.

The group exchange method reuses message numbers from the group 1 method. Although this seems unnecessarily confusing, it allows new methods to be added without having to reserve message number ranges in advance. The first message in the exchange identifies the method, and the subsequent messages in the method can use any number in the range reserved for key exchange. We will see this reuse again in the authentication protocol.

Key Generation

The types of session keys and their calculation are shown in Figure 7.33. The peers will generate whichever keys are required for the chosen session algorithms. For example, the initial IVs are not required if the peers are using a stream cipher, such as RC4.

Figure 7.33. Session Key Generation

Key

Calculation

client to server initial IV

h(K || H || "A" | | SID)

server to client initial IV

h(K || H || "B" | | SID)

client to server encryption

h(K || H || "C" | | SID)

server to client encryption

h(K || H || "D" | | SID)

client to server integrity

h(K || H || "E" | | SID)

server to client integrity

h(K || H || "F" | | SID)

K = shared secret

H = exchange hash

SID = session ID


With the SHA-1 hash, each of the calculations shown in Figure 7.33 will generate 160 bits of key material. If additional bits are required, they are generated by hashing the concatenation of K, H, and the key so far. This process is continued until a sufficient number of bits are generated. For example, to extend the bits for the client to server encryption key, we would calculate

key1 = h(K || H || "C"| |SID)

key2 = h(K || H || key1)

key3 = h(K || H || key1 || key2)

. . .

key = key1 || key2 || key3 || . . .

Either peer can initiate a rekeying by sending an SSH_MSG_KEXINIT message. This process is the same as the initial algorithm negotiation and key generation, so the peers can even renegotiate the algorithms they will use, if desired. Because the peers will use new cookies for the SSH_MSG_KEXINIT messages and will calculate a new shared secret, the newly generated keys will be distinct from the old keys.

Rekeying after transmitting a certain amount of data is always a good idea because it makes it more difficult for an attacker to gather enough ciphertext for an effective cryptanalysis. With SSHv2, there is a more immediate reason for rekeying. Recall that each packet's MAC contains an implicit sequence number that is based on a 32-bit counter. If this counter is allowed to wrap while using the same keys, the session becomes subject to replay, information leakage, and out-of-order delivery attacks [Bellare, Kohno, and Namprempre 2002]. The draft SSHv2 transport protocol specification recommends that a session be rekeyed after each gigabyte of data or after an hour of connection time without rekeying.

During the rekeying operation, the peers use the old keys and algorithms. When the rekeying operation is complete, an SSH_MSG_NEWKEYS message signals the peers to begin using the new keying material and algorithms. The SSH specification is unclear on how rekeying should take place, and many implementations don't support it [Gutmann 2005].

Service Requests

After the key exchange, the transport protocol has established its secure data stream and is now ready to start carrying data for the authorization and connection protocols. To request one of these protocols, the client sends the server an SSH_MSG_SERVICE_REQUEST message containing the service name as a string. Currently, the specification defines the two services ssh-userauth and ssh-connection.

If the server supports the service request and is willing to let the client invoke it, the server will send the client an SSH_MSG_SERVICE_ACCEPT message, which echos the service name as a string. If the server does not support the service or is unwilling to let the client invoke it, it will send the client an SSH_MSG_DISCONNECT message.

The SSHv2 Authentication Protocol

When the authentication protocol begins running, the transport protocol has already authenticated the server to the client. The authentication protocol's purpose is to authenticate the userand sometimes the client hostto the server.

Four user authentication methods are defined: public key, password, keyboard interactive, and host based. The host-based method is similar to the rhosts/RSA method from SSHv1 and is inappropriate in most situations requiring serious security. We will not discuss this method further.

The public key and password methods are functionally similar to their counterparts in SSHv1, although the protocols implementing them are different. Keyboard interactive is a general method that encompasses any authentication algorithm that can be implemented on the client side by user keyboard interaction. The advantage of this method is that new algorithms can be implemented on the server side without requiring changes to the clients. This method can be used to implement challenge/response and one-time-password schemes in SSHv2 but finds its main use in the pluggable authentication modules (PAM) framework.

The general authentication message types are shown in Figure 7.34. We'll discuss other, method-specific messages, when we cover the method in question.

Figure 7.34. General Authentication Messages

No.

Message Name

Message

50

SSH_MSG_USERAUTH_REQUEST

authorization initiation

51

SSH_MSG_USERAUTH_FAILURE

server rejects authentication attempt

52

SSH_MSG_USERAUTH_SUCCESS

server accepts authentication

53

SSH_MSG_USERAUTH_BANNER

login banner from the server


All authentication methods are initiated by the client sending the server an SSH_MSG_USERAUTH_REQUEST message. The general format of this message is shown in Figure 7.35. The method-specific data varies with the particular authentication method.

Figure 7.35. General Format of the User Authentication Request


The type field is set to SSH_MSG_USERAUTH_REQUEST. The particular type of request is given as an ASCII string in the method name field.

The user name field contains the user's name encoded as a UTF-8 string. The service name contains the name of the service for which the user is asking to be authenticated. This field is encoded as an ASCII string.

The SSH_MSG_USERAUTH_FAILURE message, shown in Figure 7.36, is sent by the server to indicate partial success or complete failure of the authentication.

Figure 7.36. The SSH_MSG_USERAUTH_FAILURE Message


The authentications list field is a list of authentication methods that the client can try instead of the failed method. The flag field provides additional message-specific semantics.

When the client successfully completes authentication to the server's satisfaction, the server responds with an SSH_MSG_USERAUTH_SUCCESS message, which ends the authentication protocol successfully. This message contains no arguments.

The final general authentication message is the SSH_MSG_USERAUTH_BANNER message. The server sends this message to request that the client display a login banner to the user. The client may decide whether to display the message. The SSH_MSG_USERAUTH_BANNER contains two strings: a UTF-8 encode string with the message itself and an RFC 3066 language tag.

The "none" Authentication Method

In the SSHv1 protocol, the server sends the client a list of supported authentication methods in the SSH_SMSG_PUBLIC_KEY message at the beginning of the protocol exchange. In SSHv2, the client requests a list of supported authentication methods by sending an SSH_MSG_USERAUTH_REQUEST message specifying the "none" authentication message. If the server does not require authentication, it can reply with an SSH_MSG_USERAUTH_SUCCESS message, but the normal procedure is to return an SSH_MSG_USERAUTH_FAILURE message with a list of supported authentication methods in the authentications list field. There is no message-specific data in the SSH_MSG_USERAUTH_REQUEST message when the method name is set to none.

The Public Key Authentication Method

The public key authentication method is similar to the RSA method from SSHv1 but is generalized to support any signature method. As we see from the tcpdump of the SSH_MSG_KEXINIT, OpenSSH supports RSA and DSS signatures.

The client requests a public key authentication by sending an SSH_MSG_USERAUTH_REQUEST message with the method name set to "publickey." The method-specific data, shown in Figure 7.37, includes three strings containing the name of the signature algorithm, the public key, and the signature itself. The flag field is set to TRUE.

Figure 7.37. Method-Specific Data for the Public Key Method


The signature is taken over the data shown in Figure 7.38. Note that the public key authentication method is different from the challenge/response protocol used in SSHv1's RSA authentication. By sending the signature along with the request, the protocol saves two packet exchanges.

Figure 7.38. Data for the Public Key Signature

Type

Data

string

session ID

byte

SSH_MSG_USERAUTH_REQUEST

string

user name

string

service

string

"publickey"

Boolean

TRUE

string

algorithm name

string

public key


If the public key is not valid for this user or if the signature does not validate, the server will respond with an SSH_MSG_USERAUTH_FAILURE message. If both tests succeed and no further authentication is required, the server will respond with an SSH_MSG_USERAUTH_SUCCESS message, and the authentication will be complete.

Computing the signature is computationally expensive and may require user interaction if the private key is protected with a password. The protocol allows the client to verify that the public key and algorithm are acceptable to the server before asking the user for the password or calculating the signature. To do this, the client sends an SSH_MSG_USERAUTH_REQUEST message with the method-specific data, as shown in Figure 7.39. The flag field is set to FALSE to distinguish this message from an actual public key authentication request. The public key blob field contains the public key and, optionally, certificates or other information.

Figure 7.39. Message-Specific Data for the Public Key Test Message


The Password Authentication Method

From the user's perspective, the SSHv2 password authentication is identical to the SSHv1 version, except that the client or server may request the user to enter a new password. This last facility is usually used by the server when a user's password has expired. The client requests a password authentication by sending the server an SSH_MSG_USERAUTH_REQUEST message with the method name set to "password." The message-specific data consists of a flag set to FALSE and a string containing the password encoded in UTF-8.

Normally, the server will respond with an SSH_MSG_USERAUTH_SUCCESS or SSH_MSG_USERAUTH_FAILURE message but can also request a new password by sending an SSH_MSG_USERAUTH_PASSWD_CHANGEREQ message (Figure 7.40). The type field is set to SSH_MSG_USERAUTH_PASSWD_CHANGEREQ (60). The prompt field contains the user prompt in the language defined by the language tag field.

Figure 7.40. The Change Password Request Message


At this point, the client can either try another authentication message or retry the password authentication, using the message-specific data shown in Figure 7.41. In this case, the flag field is set to TRUE.

Figure 7.41. Method-Specific Data for the Change Password Message


The server responds to the client's change password message with one of the following: SSH_MSG_USERAUTH_SUCCESS, indicating that the password was changed and that the authentication was successful; SSH_MSG_USERAUTH_FAILURE, indicating that the password was changed but that more authentication is needed (partial success TRUE) or that the password was not changed (partial success FALSE), due to a bad old password or password changing not being supported; or SSH_MSG_USERAUTH_CHANGEREQ, indicating that the new password was not acceptable.

The Keyboard Interactive Authentication Method

The final authentication method that we look at is the keyboard interactive method, a generalized method that can support any authentication scheme that requires only user keyboard input. One could, in principle, use this method to do ordinary password authentication, but its main use is in challenge/response and one-time-password schemes.

The client requests keyboard interactive authentication by sending the server an SSH_MSG_USERAUTH_REQUEST message with the method type set to "keyboard-interactive," and the message-specific data shown in Figure 7.42. The language tag field, if not empty, indicates the language encoding that the user prompts should be in. The submethods field is a list of authentication methods that the client would like to try. The server treats this field as a hint and is free to try whatever method it chooses.

Figure 7.42. Message-Specific Data for the Keyboard Interactive Message


The server may respond with an SSH_MSG_USERAUTH_FAILURE message if it does not support keyboard interactive authentication or an SSH_MSG_USERAUTH_SUCCESS message if no further authentication is required. Normally, however, the server will respond with the SSH_MSG_USERAUTH_INFO_REQUEST (60) message shown in Figure 7.43.

Figure 7.43. The SSH_MSG_USERAUTH_INFO_REQUEST Message


The name and instruction fields are displayed to the user. Either or both fields may be empty. The language tag field is intended to indicate to the client which language encoding should be used for the messages it displays to the users. The draft specification recommends that this field be empty and that the peers use the encodings negotiated during key exchange.

The number of prompts field tells the client how many prompt/echo pairs follow. These are labeled prompt1 . . . promptn and echo1 . . . echon in Figure 7.43. Each prompti field contains a prompt for the user ("Password:", for example), and the corresponding echoi flag tells the client whether to echo the response to the user's terminal.

On receipt of the SSH_MSG_USERAUTH_INFO_REQUEST message, the client displays the name and instruction fields on the user's display and then prompts the user with each of the included prompts, either echoing the response or not, as indicated by the corresponding echo flag. The server can send additional SSH_MSG_USERAUTH_INFO_REQUEST messages but only after the client responds to the current one.

After prompting the user and gathering the replies, the client will respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message (Figure 7.44). The number of responses field must contain the same number as the server's number of prompts field. The responsei fields carry the user's response to the server's prompts.

Figure 7.44. The SSH_MSG_USERAUTH_INFO_RESPONSE Message


The Connection Protocol

After authentication, SSH starts the ssh-connection service, which handles remote shells, remote execution of commands, X11 forwarding, and TCP/IP port forwarding. With the exception of file transfer utilities, such as scp, these services are implemented similarly to the way they were in SSHv1.

As in SSHv1, multiple channels can be multiplexed onto the secure data stream provided by the transport protocol. As a result, there are two classes of messages in the connection protocol: channel messages, which apply to a particular channel, and global messages, which are not associated with a channel. The message types and numbers are given in Figure 7.45.

Figure 7.45. SSHv2 Channel Messages

No.

MessageName

Message

80

SSH_MSG_GLOBAL_REQUEST

global message

81

SSH_MSG_REQUEST_SUCCESS

global message succeeded

82

SSH_MSG_REQUEST_FAILURE

global message failed

90

SSH_MSG_CHANNEL_OPEN

channel open request

91

SSH_MSG_CHANNEL_OPEN_CONFIRMATION

channel open request succeeded

92

SSH_MSG_CHANNEL_OPEN_FAILURE

channel open failed

93

SSH_MSG_CHANNEL_WINDOW_ADJUST

open flow control window

94

SSH_MSG_CHANNEL_DATA

data-bearing message for a channel

95

SSH_MSG_CHANNEL_EXTENDED_DATA

extended channel data (STDERR, e.g.)

96

SSH_MSG_CHANNEL_EOF

end of file for channel data

97

SSH_MSG_CHANNEL_CLOSE

channel close request

98

SSH_MSG_CHANNEL_REQUEST

channel-specific request

99

SSH_MSG_CHANNEL_SUCCESS

channel request succeeded

100

SSH_MSG_CHANNEL_FAILURE

channel request failed


The global request message has the general form shown in Figure 7.46. The type field is set to SSH_MSG_GLOBAL_REQUEST, and the specific request is carried as an ASCII string in the request name field. The want reply field is a Boolean that's set to TRUE if the sender wants a reply to the request and FALSE otherwise. When the want-reply flag is TRUE, the peer will respond with either an SSH_MSG_REQUEST_SUCCESS or an SSH_MSG_REQUEST_FAILURE message. Both of these messages normally have only a type field, but the SSH_MSG_REQUEST_SUCCESS message may include data specific to the request that it is acknowledging.

Figure 7.46. General Form of the SSH_MSG_GLOBAL_REQUEST Message


The SSH_MSG_CHANNEL_OPEN, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, and SSH_MSG_CHANNEL_OPEN_FAILURE messages have similar general forms. The SSH_MSG_CHANNEL_OPEN message, shown in Figure 7.47, requests that the peer allocate a new data channel. As we've seen before, each peer will have its own channel number. The sender channel field is the number that the message sender has assigned to the channel. The channel type field is the type of channel that the sender is requesting. This field is encoded in ASCII.

Figure 7.47. General Form of the SSH_MSG_CHANNEL_OPEN Message


The initial window size field is used for flow control. The maximum packet size field indicates the largest packet that the sender is willing to receive from its peer.

If the peer agrees to open the channel, it will respond with an SSH_MSG_CHANNEL_OPEN_CONFIRMATION message (Figure 7.48). The recipient channel is the channel number that the original sender assigned in the SSH_MSG_CHANNEL_OPEN message. The sender channel is the channel number that this sender is assigning. The other fields are identical to those in the SSH_MSG_CHANNEL_OPEN message.

Figure 7.48. General Form of the SSH_MSG_CHANNEL_OPEN_CONFIRMATION Message


If the peer cannot or is unwilling to open the channel, it will reply with the SSH_MSG_CHANNEL_OPEN_FAILURE message, shown in Figure 7.49. The reason code field is a numeric value giving the reason for the failure. Currently defined values are given in Figure 7.50. The textual information field gives further information about the failure. It is intended for human consumption. The language tag field indicates the language for the textual information field.

Figure 7.49. The SSH_MSG_CHANNEL_OPEN_FAILURE Message


Figure 7.50. Channel Open Failure Reason Codes

Code

Value

SSH_OPEN_ADMINISTRATIVELY_PROHIBITED

1

SSH_OPEN_CONNECT_FAILED

2

SSH_OPEN_UNKNOWN_CHANNEL_TYPE

3

SSH_OPEN_RESOURCE_SHORTAGE

4


Data Transfer

Data transfer in SSHv2 is flow controlled in a manner vaguely reminiscent of TCP's flow control. Each side maintains a "window" that its peer can send data into. When the window is filled up, the peer must stop sending data. As buffer space becomes available, the receiving side informs its peer by sending a SSH_MSG_CHANNEL_WINDOW_ADJUSTMENT message that indicates how many more bytes the peer can send. This message contains two unsigned integers: the recipient channel number and a bytes to add field that indicates how much to expand the window.

Data is carried in SSH_MSG_CHANNEL_DATA messages. These messages have two fields: the usual recipient channel number and the data itself, carried as a string.

Because a channel can carry more than one type of data, an SSH_MSG_CHANNEL_EXTENDED_DATA message (Figure 7.51) carries the other data types. Currently, this message is used only to carry STDERR data in interactive sessions. The data type field indicates the type of extended data the message is carrying. The only defined type at this writing is SSH_EXTENDED_DATA_STDERR (1).

Figure 7.51. The SSH_MSG_CHANNEL_EXTENDED_DATA Message


When finished sending data on a channel, a peer can send an SSH_MSG_CHANNEL_EOF message. This message contains a single unsigned integer carrying the recipient's channel number. The message does not close the channel, and the other side may continue to send datain this respect, it is like the TCP EOF that merely indicates that one side has finished sending data.

Either peer can close the channel by sending an SSH_MSG_CHANNEL_CLOSE message, which again contains only the recipient's channel number. The peer receiving this message must respond with its own SSH_MSG_CHANNEL_CLOSE message, after which no further data can be sent by either side.

Shell and Remote Command Sessions

To start a shell session or execute a remote command, the client opens a session channel by sending the server an SSH_MSG_CHANNEL_OPEN message with the channel type set to "session." If needed, the client can request a pseudo-tty terminal by sending an SSH_MSG_CHANNEL_REQUEST message. The general form of this message is shown in Figure 7.52.

Figure 7.52. The SSH_MSG_CHANNEL_REQUEST Message


To request a pseudo-tty, the request type field is set to "pty-req." The additional information shown in Figure 7.53 is also included. This message is almost identical to the SSHv1 SSH_CMSG_REQUEST_PTY message.

Figure 7.53. Message-Specific Data for a Pseudo-TTY Request


If the want reply flag is TRUE, the server will reply with either an SSH_MSG_CHANNEL_SUCCESS or an SSH_MSG_CHANNEL_FAILURE message. Both of these messages have a single argument carrying the recipient channel number.

Once the channel is established and a pseudo-tty is started, if needed, the client can request the server to either start a shell or execute a command by sending another SSH_MSG_CHANNEL_REQUEST message. These commands have the request type field set to either "shell" or "exec." When the request type is "exec," an additional string parameter carries the name of the command to execute. Before starting the shell or command, the client can set environment variables for them by sending an SSH_MSG_CHANNEL_REQUEST message with the request type field set to "env." Two strings in the request-specific data contain the variable name and its value.

When it terminates, the command or shell can return an exit status to the client by sending an SSH_MSG_CHANNEL_REQUEST with the request type field set to "exit-status," and an additional unsigned integer containing the exit status. The want reply flag must be set to FALSE for this message.

If the shell or command terminates prematurely with a signal, the server sends an SSH_MSG_CHANNEL_REQUEST message with the request type field set to "exit-signal." Additional data about the signal is included in the message-specific data, as shown in Figure 7.54. As with the "exit-status" message, the want reply field is set to FALSE. The core dumped flag is set to TRUE if a core dump resulted and to FALSE otherwise.

Figure 7.54. Request-Specific Data for the Exited with Signal Message


The client can send a signal to the command or shell executing on the server by sending the server an SSH_MSG_CHANNEL_REQUEST message with the request type field set to "signal." The message-specific data is a string containing the name of the signal, without the "SIG." As with the exit messages, the want reply flag is set to FALSE. Not all servers implement signals, of course, so the server will ignore this message if it does not support signals or does not recognize the signal type.

Two other channel messages are associated with interactive sessions. The first is the "window-change" request, which informs the server of a change in the client's terminal window dimensions. The message-specific data comprises four unsigned integers that contain the window's new width and height, first in columns and rows and then in pixels. The want reply flag is FALSE.

The other message type associated with interactive sessions is the "xon-xoff" message, which allows the client to do manual (^S/^Q) flow control. The server sends this message to the client to tell it whether the client can do manual flow control. The message-specific data is a single Boolean flag, can do, which is TRUE if the client is allowed to perform manual flow control and FALSE otherwise. The want reply flag is FALSE for this message.

X11 Forwarding

X11 forwarding under SSHv2 works pretty much the way it does under SSHv1. The client requests forwarding by sending the server an SSH_MSG_CHANNEL_REQUEST message with the request type set to "x11-req." The request-specific information is shown in Figure 7.55. The single connection field is a Boolean that indicates whether the server should accept multiple X11 connections. The other fields serve the same purposes they did in SSHv1 X11 forwarding.

Figure 7.55. Request-Specific Data for the X11 Forwarding Request Message


When an X11-client connects to the proxy server, the SSH server opens a channel to the client by sending an SSH_MSG_CHANNEL_OPEN message, with the channel type set to "x11." The request-specific data comprises a string containing the originator's address and an unsigned integer containing the originator's source port. As usual, the client is expected to reply with either an SSH_MSG_CHANNEL_OPEN_CONFIRMATION or an SSH_MSG_CHANNEL_OPEN_FAILURE message.

Port Forwarding

As with X11 forwarding, SSHv2 port forwarding is similar to its SSHv1 counterpart. The client may forward a local port to the server at any time by sending the server an SSH_MSG_CHANNEL_OPEN message with the channel type field set to "direct-tcpip." The request-specific data, shown in Figure 7.56, indicates the host and port to connect to and the host and port of the connection's originator.

Figure 7.56. Request-Specific Data for a Local Port Forwarding Message


Remote port forwarding is handled just as it is in SSHv1. The client requests the server to forward a port to it by sending an SSH_MSG_GLOBAL_REQUEST message with the request type set to "tcpip-forward." The request-specific data comprises a string containing the address to bind and an unsigned integer containing the port to forward. If the client specifies 0 as the port to forward, the server will bind the next available port number. In this case, if the want reply flag is TRUE, the server's SSH_MSG_GLOBAL_REQUEST_SUCCESS message will include an integer indicating the port bound.

When it connects to the server, a remote host will send the client an SSH_MSG_CHANNEL_OPEN message with the channel type field set to "forwarded-tcpip." The request-specific data, shown in Figure 7.57, contains the address and port that was connected to and the originator's address or port.

Figure 7.57. Request-Specific Data for a Remote Port Forwarding Message


The client can cancel a forwarding request by sending the server an SSH_MSG_GLOBAL_REQUEST message with a request type of "cancel-tcpip-forward," message-specific data comprising a string with the address that was bound, and an unsigned integer containing the port that was bound.

Subsystems

SSHv2 introduced a new abstraction layer called subsystems. A good way of understanding subsystems is to think of them as a sort of inetd for SSH. The idea is that the server's system administrator can give arbitrary names to commands that the client may request the server to run.

The most common example is sftp, an alternative interface to the scp functionality. Under SSHv2, sftp is defined as a subsystem. Thus, when the sftp client runs, it spawns ssh as a subprocess and asks it to run the sftp subsystem on the server. From a functional point of view, this is identical to what happens with SSHv1 except that the name of the process implementing the sftp server need not be "sftp" or even known by the client at all.

The server's system administrator configures the sftp subsystem by providing a mapping between the subsystem name and the name and path of the program implementing it. The system administrator can configure arbitrary subsystems by merely providing a mapping between the subsystem name and the command implementing it. For example, we could implement an rbiff subsystem by mapping the subsystem name "rbiff" to the command rbiffd. A more realistic example of SSH subsystems is at <http://www.columbia.edu/kermit/skermit.html>, which describes how to run kermit as an SSH subsystem.

Pushing our inetd analogy a little further, some systems could be implemented internally by sshd, much like the echo command is implemented internally by most implementations of inetd. Currently, no subsystems are implemented in this way, but the capability exists.

The client requests the server to invoke a subsystem by sending the server an SSH_MSG_GLOBAL_REQUEST message with the request type field set to "subsystem." The message carries the name of the system in the message-specific information as a string.

Security Issues with SSHv2

As we remarked earlier, SSHv2 was written to address certain security flaws in SSHv1. Although no defects as devastating as the CRC-32 MAC exploit have been discovered in SSHv2, some problems need to be addressed. A simple chosen plaintext attack, usually called Rogaway's attack, against block ciphers in CBC mode is described in [Dai 2002]. The attack requires knowing what the next IV for the block cipher will be, but in CBC mode, one need merely observe the previous cipher block, because it will be used as the next IV.

In Rogaway's attack, the attacker suspects that the value of plaintext block Pi is X and wants to verify that guess. The attacker observes that the last cipher block sent was Cj-1 and so chooses the plaintext block Pj = X Ci-1 Cj-1 to be encrypted. Now with CBC mode, we have

Cj = EK(Pj Cj-1) = EK(X Ci-1 Cj-1 Cj-1) = EK(X Ci-1)

so if Cj = Ci, the attacker will have verified that X = Pi.

The attack is a little more difficult than indicated, because the first block of a packet starts with the two length fields (40 bits), over which the attacker does not have complete control. This implies that the attacker may have to wait several packets to launch the attack. See [Bellare, Kohno, and Namprempre 2002] for a complete analysis.

Dai recommended using RC4 to avoid this problem. The draft SSH architecture document from the IETF SECSH working group recommends the insertion of SSH_MSG_IGNORE messages to ensure that the attacker will not know the next IV.

Another attack on the SSHv2 transport protocol is described in [Bellare, Kohno, and Namprempre 2002]. The attack is a chosen ciphertext attack that also takes advantage of CBC mode. The idea is that the attacker knows one message Mi and suspects that another message, Mj, is identical or related to it. The attacker can verify this guess by sending the receiver specially crafted ciphertext. If the guess is correct, the receiver will accept the ciphertext as legitimate. If the guess is incorrect, the message will fail the authentication step, and the receiver will disconnect. The details of the attack are in [Bellare, Kohno, and Namprempre 2002].

We can make two observations about these attacks. First, neither approaches the seriousness of the attacks on SSHv1. The most the attacker can do is verify a previous guess as to the value of a block or that two blocks are the same or related. Second, both attacks depend on the underlying encryption using CBC mode.

The second observation suggests that we should consider using something other than a block cipher in CBC mode for encryption. As Dai suggests, RC4 is one possible alternative. [Bellare, Kohno, and Namprempre 2002] considers several other alternatives and concludes that using block encryption in CTR mode is the best solution. The authors have submitted a draft RFC to the SECSH working group, recommending that CTR mode be added to the list of supported block ciphers. The authors also provide tighter bounds on the amount of data that the SSHv2 transport layer can safely send before rekeying.

At the current time, SSHv2 appears to be reasonably secure. The known exploits are difficult to mount and yield relatively small results. These exploits depend on weaknesses in the CBC mode of block ciphers and can therefore be avoided by using RC4 or by using CTR mode instead of CBC mode with block ciphers. The modularity of the SSHv2 architecture and the ability to negotiate the security mechanisms for each session make it easy for SSHv2 to adapt to newly discovered exploits.

As always, we should keep in mind that a secure application can be attacked in many ways, some not directly aimed at the cryptographic mechanisms. For example, an interesting side-channel attack on SSH is described in [Song, Wagner, and Tian 2001]. In this attack, keystroke timings from an interactive SSH session are measured by observing the packet times. Statistical techniques are used to infer information about the text, including in some cases the text typed. One application of these techniques was able to reduce the work in an exhaustive search for passwords by a factor of 50. This attack depends on the fact that in interactive mode, SSH sends each character typed in a separate packet.


Previous Page
Next Page