I have been having troubles with a question where I had to test that an SSH implementation drops (or reject) packets greater than 262144. Thus, after reading the RFCs and the SSH protocol standard, I had only two solution I found is implement my own SSH protocol, or (easy and chose way) modify an existing implementation of SSH.

If we look the RFC 4253 [1], which is the RFC of SSH, we have the following:


We can send and receive a packet with a payload of 32768 bytes or less and a total packet of 35000 bytes. Also, says that implementations should support large packets but check that these large packets have a reasonable length which leaves the way open to the maximum supported length to the implementations.

I have been reviewing the most common implementation of SSH, and I have found that:

OpenSSH [2]:

106 #define PACKET_MAX_SIZE (256 * 1024)
           [...]
246        state->connection_in = -1;
247        state->connection_out = -1;
248        state->max_packet_size = 32768;
249        state->packet_timeout_ms = -1;
250        state->p_send.packets = state->p_read.packets = 0;

LibSSH;

priv.h [3]:

/* some constants */
#ifndef MAX_PACKET_LEN
#define MAX_PACKET_LEN 262144
#endif
channel.c [4]:
/*
 * All implementations MUST be able to process packets with an
 * uncompressed payload length of 32768 bytes or less and a total packet
 * size of 35000 bytes or less.
 */
#define CHANNEL_MAX_PACKET 32768
#define CHANNEL_INITIAL_WINDOW 64000


LibSSH2:

libssh2_priv.h [5]:

/* RFC4253 section 6.1 Maximum Packet Length says:
 *
 * "All implementations MUST be able to process packets with
 * uncompressed payload length of 32768 bytes or less and
 * total packet size of 35000 bytes or less (including length,
 * padding length, payload, padding, and MAC.)."
 */
#define MAX_SSH_PACKET_LEN 35000

libssh2.h [6]:

/* Maximum size to allow a payload to compress to, plays it safe by falling
   short of spec limits */
#define LIBSSH2_PACKET_MAXCOMP      32000

/* Maximum size to allow a payload to deccompress to, plays it safe by
   allowing more than spec requires */
#define LIBSSH2_PACKET_MAXDECOMP    40000

/* Maximum size for an inbound compressed payload, plays it safe by
   overshooting spec limits */
#define LIBSSH2_PACKET_MAXPAYLOAD   40000


The purpose, which is send a large packet in order to verify the max packet length supported by a SSH implementation; we need to modify some of these libraries, in my case for simplicity I have used libssh-9.5.0, where i have modified the code to allow send packets bigger than 262144 bytes (most common maximum packet length used by the implementation), and I have also modified the window length with hardcoded length during the negotiation. The maximum length I have hardcoded is 280000 bytes, which is greater than 262144. I have also added some verbose output in order to see what is happening, the patch for libssh can be downloaded from the following link.


Someone could say it is stupid, why have you tried to send a large packet that the implementations do not allow to? Easy answer, one security test have this check in their list (or just hacking!!!)

E.g. Protection Profile of Network Devices of NIAPP [7].

FCS_SSHC_EXT.1.3 The  TSF  shall  ensure  that,  as described  in  RFC  4253,  packets  greater than [assignment: number of bytes] bytes in  an SSH transport  connection  are dropped.


Finally, modifying a bit the example SSH client of libssh I have develop a fast and dirty program that can check the SSH maximum packet length accepted by a SSH server. This program can be downloaded from the following link.

To compile it you have to install the patched version of libssh and compile with the following command:

gcc ssh_maxpacket.c -o ssh_maxpacket -lssh


In the following examples, it is the case inverse, my OpenSSH client will connect to a SSH server that will send different packets length:

OpenSSH receiving packetof different lengths:



Of course OpenSSH accepts packet until 262144 bytes, but if the packet is greater directly close the connection.

For the server is very similar to the client way, you can find an server example in the folder examples of libssh :)

Maybe this can help someone...


[1] https://tools.ietf.org/html/rfc4253

[2] https://github.com/openssh/openssh-portable/blob/master/packet.c

[3] https://git.libssh.org/projects/libssh.git/plain/include/libssh/priv.h

[4] https://git.libssh.org/projects/libssh.git/plain/src/channels.c

[5] https://github.com/libssh2/libssh2/blob/6c7769dcc422250d14af1b06fce378b6ee009440/src/libssh2_priv.h

[6] https://github.com/libssh2/libssh2/blob/6c7769dcc422250d14af1b06fce378b6ee009440/include/libssh2.h

[7] https://www.niap-ccevs.org/MMO/PP/CPP_ND_V2.2E.pdf