urgent security release: 10.6p2

Andy Lutomirski luto at kernel.org
Fri Nov 6 11:36:36 AEDT 2026


On Thu, Nov 5, 2026, at 1:10 AM, Damien Miller wrote:
> OpenSSH 10.6p2 has been released with a workaround for a critical
> vulnerability.
>
> https://openssh.com/releasenotes.html#10.6p2
>
> If you operate a Linux system that uses musl libc without
> PAM (Alpine Linux is one example) then stop reading and set
> PasswordAuthentication=no or disable SSH for these systems IMMEDIATELY.
>
> This vulnerability does not exist on non-Linux systems, Linux/glibc
> systems and Linux systems that use PAM for password authentication.
>
> We consider the root cause of this bug to be outside OpenSSH itself, but
> we're in a good position to deliver a mitigation quickly.

I tried to analyze the control flow associated with this bug, and I'm not sure it's entirely valid to call it musl's bug.  musl anticipates that someone might call crypt("garbage", "*") and applies a workaround:

https://git.musl-libc.org/cgit/musl/tree/src/crypt/crypt_des.c#n1015

But openssh-portable manages to bypass musl's workaround.  sys_auth_passwd does:

	/*
	 * Encrypt the candidate password using the proper salt, or pass a
	 * NULL and let xcrypt pick one.
	 */
	if (authctxt->valid && pw_password[0] && pw_password[1])
		salt = pw_password;

https://github.com/openssh/openssh-portable/blob/master/auth-passwd.c#L223-L224

and later, in xcrypt:

	if (salt == NULL)
		salt = pick_salt();

https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/xcrypt.c#L121-L122

IOW sys_auth_password already detected a crypted password shorter than 2 bytes, but instead of remembering that it's invalid, it proceeded to call crypt(attacker-entered password, made up salt).  Note that   But the control flow was such that getting a result  equal to the crypted password (which is *neither* of the arguments actually passed to crypt) was a success.

The whole control and data flow here makes me (as a somewhat seasoned reviewer of security-sensitive code) extremely uneasy.  I understand crypt() is a fundamentally awful API, but still, openssh-portable could do better.

At the very least, I think the if (... && pw_password[0] & pw_password[1]) should do something like:

    else
        must_fail = true;

But an even better improvement would be to isolate the entire fake password check procedure in its own function that, by construction, cannot confuse the caller:

    void check_password_against_fake_account(const char *password);

and all of the fake salt, etc logic could be isolated in a portion of the control flow graph that cannot confuse anything else.

(I have no affiliation whatsoever with the musl project.)

--Andy


More information about the openssh-unix-dev mailing list