Report on findings after testing OpenSSH server implementations

Paul Fiterau paul.fiterau_brostean at it.uu.se
Sat Oct 16 00:23:51 AEDT 2021


Hello!

I am part of a testing research group at Uppsala University. We have
recently applied our model-based testing technique to OpenSSH servers
and would like to share our findings in terms of potential issues found
and receive feedback of course. The version we tested is 8.8p1, which
was running on a Ubuntu 20.04 machine. For each issue, we give an
input/output sequence that exposes it, and relevant quotes for the RFC.
We can also provide reproduction material if asked. None of the issues
appear to have any security implications.

Before going over the issues, we wanted to first ask you about one
behavior which we struggle to understand. We notice that OpenSSH buffers
higher-layer messages received during part of the key re-exchange
process. Is this really necessary given that a client should not
generate these messages, according to RFC 4253 (see quote below).
Wouldn't it be easier to simply discard/reject these messages (like
Dropbear does, which would solve Issues 1 and 2)? What we want to know,
concretely, is, if there is a practical reason for this behavior/design
choice.

RFC 4253, page 19:

"  After the SSH_MSG_KEXINIT message exchange, the key exchange
    algorithm is run.  It may involve several packet exchanges, as
    specified by the key exchange method.

    Once a party has sent a SSH_MSG_KEXINIT message for key exchange or
    re-exchange, until it has sent a SSH_MSG_NEWKEYS message (Section
    7.3), it MUST NOT send any messages other than:

    o  Transport layer generic messages (1 to 19) (but
       SSH_MSG_SERVICE_REQUEST and SSH_MSG_SERVICE_ACCEPT MUST NOT be
       sent);

    o  Algorithm negotiation messages (20 to 29) (but further
       SSH_MSG_KEXINIT messages MUST NOT be sent);

    o  Specific key exchange method messages (30 to 49)."


Now onto the issues.


Issue 1. Processing upper-layer data before key re-exchange is complete.

When performing key re-exchange (rekeying), OpenSSH does not wait for
the client NEWKEYS before processing higher-layer messages. Concretely,
it processes higher-layer messages (secured with old keys) received
between sending NEWKEYS to the client and receiving NEWKEYS from the
client. Technically, the RFC does not explicitly mention that servers
should wait for NEWKEYS from the client before processing messages. But
intuitively, a key re-exchange (like the initial key exchange) is only
complete once keys are renewed and deployed in both directions. Before
that, it seems to us that higher-layer messages should not be processed,
as is the case for the initial key exchange (which key re-exchange is
supposed to be similar with). Not to mention that a client is not
supposed to send any higher-layer messages before sending NEWKEYS.

Sequence:

KEXINIT/KEXINIT
KEX30/KEX31+NEWKEYS
NEWKEYS/NO_RESPONSE
SERVICE_REQUEST(ssh-userauth)/SERVICE_ACCEPT
USERAUTH_REQUEST/USERAUTH_SUCCESS+GLOBAL_REQUEST
KEXINIT/KEXINIT KEX30/KEX31+NEWKEYS
CHANNEL_OPEN/CHANNEL_OPEN_SUCCESS


Issue 2. Non-conforming response to CHANNEL_CLOSE.

The presence of Issue 1 leads to Issue 2. The RFC says that on receiving
a CHANNEL_CLOSE to close a channel, implementations SHOULD reply with
CHANNEL_CLOSE. OpenSSH does not always follow this requirement. In
particular, when receiving CHANNEL_CLOSE during key exchange, it
silently consumes this message and only generates CHANNEL_CLOSE response
after receiving NEWKEYS from the client. What is interesting is that,
during that same key re-exchange, OpenSSH processes CHANNEL_OPEN and
generates CHANNEL_OPEN_SUCCESS  before NEWKEYS is received.

RFC 4254, page 9:

"  When either party wishes to terminate the channel, it sends
    SSH_MSG_CHANNEL_CLOSE.  Upon receiving this message, a party MUST
    send back an SSH_MSG_CHANNEL_CLOSE unless it has already sent this
    message for the channel.  "

Sequence:

KEXINIT/KEXINIT
KEX30/KEX31+NEWKEYS
NEWKEYS/NO_RESPONSE
SERVICE_REQUEST(ssh-userauth)/SERVICE_ACCEPT
USERAUTH/USERAUTH_SUCCESS+GLOBAL_REQUEST
KEXINIT/KEXINIT KEX30/KEX31+NEWKEYS
CHANNEL_OPEN/CHANNEL_OPEN_SUCCESS
CHANNEL_CLOSE/NO_RESPONSE
CHANNEL_OPEN/CHANNEL_OPEN_SUCCESS
CHANNEL_CLOSE/NO_RESPONSE
NEWKEYS / CHANNEL_CLOSE + CHANNEL_CLOSE


Issue 3. Rekey not supported pre-authentication.

We found that rekey is not supported after key exchange is complete but
before the user authenticates.

Sequence:

KEXINIT/KEXINIT
KEX30/KEX31+NEWKEYS
NEWKEYS/NO_RESPONSE
SERVICE_REQUEST(ssh-userauth)/SERVICE_ACCEPT
KEXINIT/UNIMPLEMENTED


Issue 4. Use of UNIMPLEMENTED when the RFC says otherwise (very minor
but might as well mention it).

RFC 4253, page 24:

"  If the server rejects the service request, it SHOULD send an
    appropriate SSH_MSG_DISCONNECT message and MUST disconnect."

Sequence:

KEXINIT/KEXINIT
SERVICE_REQUEST(ssh-userauth)/UNIMPLEMENTED

RFC 4252, page 6:

"  SSH_MSG_USERAUTH_SUCCESS MUST be sent only once.  When
    SSH_MSG_USERAUTH_SUCCESS has been sent, any further authentication
    requests received after that SHOULD be silently ignored."

Sequence:

KEXINIT/KEXINIT
KEX30/KEX31+NEWKEYS
NEWKEYS/NO_RESPONSE
SERVICE_REQUEST(ssh-userauth)/SERVICE_ACCEPT
USERAUTH/USERAUTH_SUCCESS+GLOBAL_REQUEST
USERAUTH/UNIMPLEMENTED

Thanks for any feedback, particularly on Issue 1 and buffering!

Paul.








När du har kontakt med oss på Uppsala universitet med e-post så innebär det att vi behandlar dina personuppgifter. För att läsa mer om hur vi gör det kan du läsa här: http://www.uu.se/om-uu/dataskydd-personuppgifter/

E-mailing Uppsala University means that we will process your personal data. For more information on how this is performed, please read here: http://www.uu.se/en/about-uu/data-protection-policy


More information about the openssh-unix-dev mailing list