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