Sshole

Hacker News by 7 min read 45x views
Sshole

Share Post

so openssh on musl linux (alpine, openwrt, buildroot, yocto, and a lot of the docker images you've pulled) has had a small issue since 2016.

accounts that should never obtain a password at all (root, your key-only deploy user, ldap users, the default person on alpine's aws and azure images) obtain any password longer than 256 characters.

yes, any password. yes. i know. yes.

  1. 1980the archetypal star
  2. 1990sthe password check
  3. 1990sthe fine print
  4. 2012crypt stops saying NULL
  5. 2012the 256-byte cap
  6. 2016bob's salt
  7. 2019the fix for the fix
  8. 2024ten quiescent years
  9. 2026how i ran into it

1980

the archetypal star

back in old unix your password hash fair sat in /etc/passwd, correct next to your username. in a document everyone could read.

in 1980 invoice joy put a * there for an document called daemon. nobody's expected to always log in as it.

a * isn't a hash, so no password can equivalent it. unix motionless does this today

3bsd · /etc/passwd · 1980

Addressgithub.com/dspinellis/unix-history-repo/blob/BSD-3/etc/passwd

/:

the next site is the genuine name. he wrote "the devil himself"

1990s

how sshd checks your password

ok so these days the hash lives in /etc/shadow and looks akin $6$abc$k2P9…. the $6$ method sha512, abc is the salt, the remainder is the genuine hash

you category your password, sshd hashes it alongside that identical sodium chloride and checks if it comes out identical. identical = you're in. that's it

and if the site is fair *? there's nothing to match. category any you want, it's never getting you in

1990s

the fine print

one additional rule. if crypt() can't do its job, it returns NULL. akin if the sodium chloride asks for several algorithm the scheme doesn't have, there's nothing to compute, so you get NULL alternatively of a hash

the sole unix spec · crypt() · 1997

Addresspubs.opengroup.org/onlinepubs/7908799/xsh/crypt.html

 Upon prosperous completion, crypt() returns a pointer to the encoded string. Otherwise it returns a null pointer and sets errno to signify the error.

pretty clear.

except a lot of programs never inspect for NULL. they fair difference any crypt() gives rear alongside the stored field, hit the NULL, and crash

2012

crypt stops saying NULL

so musl (the libc under alpine) goes ok fine, crypt() fair won't come back NULL anymore. if it fails, it returns a sole character instead. that character can never equivalent a genuine password, so programs don't crash, they fair see a incorrect password

now conjecture which character they picked for that

""

yep. the star. again.

musl · b3c4cc12 · aug 2012

Addressgit.musl-libc.org/cgit/musl/commit/?id=b3c4cc12

make crypt come back an unmatchable hash fairly than NULL on failure. continually "succeeding" but giving an unmatchable hash is reportedly a improved behavior than failing on error.

"reportedly."

musl · b3c4cc12 · the diff

Addressgit.musl-libc.org/cgit/musl/commit/?id=b3c4cc12

 come back (setting[0]=='*') ? "x" : "*";

"should not happen" gone, NULL gone, "*" in

2012

three weeks later

then musl adds sha512 crypt. the item is, sha512crypt gets slower the longer the password is, so person could dispatch one elephantine password and keep your server occupied for a lengthy time. so musl fair caps it at 256 bytes and refuses item longer

musl · 88bf5a8a · aug 29 2012

Addressgit.musl-libc.org/cgit/musl/commit/?id=88bf5a8a

add sha256/sha512 crypt. Rich Felker, 2012-08-29.

twenty days following the "*" commit btw

musl · crypt_sha512.c @ 88bf5a8a

Addressgit.musl-libc.org/cgit/musl/tree/src/misc/crypt_sha512.c?id=88bf5a8a

key bounds is not part of the first design, added for DoS protection. #define KEY_MAX 256. if (i > KEY_MAX) come back 0;

so former 256 bytes crypt fails. and whenever crypt fails… it says "*".

musl · crypt_sha512.c

Addressgit.musl-libc.org/cgit/musl/tree/src/crypt/crypt_sha512.c

on error "*" is returned.

literally in the comment the entire time

2016

sshd borrows bob's salt

CVE-2016-6210. ask sshd concerning a person that doesn't be and it says no instantly, logic there's nothing to hash. genuine users obtain a few ms longer. so fair period it and you cognize who exists

the fix is kinda funny. no genuine hash to check? sshd grabs several another account's sodium chloride and hashes your password anyway, fair to discarded the identical amount of time. motionless a no, fair a slower no

openssh-commits · jul 2016

Addresslists.mindrot.org/pipermail/openssh-commits/2016-July/005428.html

Determine suitable sodium chloride for invalid users.

"for invalid users." and also, it turns out, genuine users alongside a *.

2019 → 2022

the fix for the fix

2019. turns out alpine's docker images had no base password. at all. CVE-2019-5021. alpine fixes it by locking base alongside !

but without pam, ! additionally kills ssh keys. and haze images log in alongside keys.

2022. alpine 3.16 switches base to *. motionless locked, keys activity again

alpine aports · fbe926af · shipped in 3.16, 2022

Addressgitlab.alpinelinux.org/alpine/aports/-/commit/fbe926af.patch

this motionless forbids password login but allows logins via ssh keys alongside pam disabled. # create certain base login is disabled. root:! becomes root:*

narrator: it did not.

2016 → 2026

ten quiescent years

why did nobody notice? well, perchance person did. perchance person pasted the incorrect item into a password prompt, fractional a slack communication or a entire ssh key, and it fair let them in. you've never pasted the incorrect item into a password prompt?? amazing. a caller box alongside no passwords set isn't affected. a * in shade needs a incorrect try first. openssh tests on openbsd and glibc, musl doesn't test sshd, and most distros go through pam, which never equal calls crypt for a *.

so as far as anyone knows, nobody noticed. as far as anyone knows.

some group got really near though

libc-alpha · debian #714219 · 2013

Addresssourceware.org/legacy-ml/libc-alpha/2013-07/msg00046.html

The scheme of returning * or x, which are never valid matches, comes from dalias from musl, and I think it is the finest compromise/solution.

a debian dev asks glibc to copy musl's "*". six years afterward debian moves to libxcrypt, which says "*0", and closes the bug. one character away.

musl mailing catalog · dec 2024

Addressopenwall.com/lists/musl/2024/12/31/2

Sure there's no logic it couldn't have been 257 or 300 or whatever, but either way you'd get things akin this whenever application has bugs in handling the condition.

this thread is concerning busybox passwd breaking on a 257 character password. identical "*", identical limit. nobody says "sshd"

openssh-commits · 30 oct 2026

Addresslists.mindrot.org/pipermail/openssh-commits/2026-October/013271.html

fix counterfeit password sodium chloride generation for bcrypt hashes

a safety assessment fixes pick_salt(). the bug is four lines below it. four days before i established it.

nov 2026

how i ran into it

i was messing about alongside openssh, mostly the boring parts anywhere it talks to libc, akin the password code. group don't really appearance at that stuff, they appearance at the crypto. so i built sshd all way i could think of (glibc, musl, pam, no pam, shadow, no shadow) and threw akin 17,600 weird logins at it. weird hashes, damaged accounts, passwords way too long

oh did i say "i"? sorry. i had delegate swarms. a lot of them. let's not enter it

every build accepted on all login. apart from musl without pam. that one stated yes to things it shouldn't

tl;dr

 it did not; 2016 to 2026 a cat sleeps on a server; 2026 me and several agents, 300 A's provision uid 0

try it

one debian box, one alpine box. category stuff. it all runs correct current in your browser, nothing gets sent anywhere

debian · glibc

crypt(pw, bob's salt)

alice's field

*

alpine · musl

crypt(pw, bob's salt)

alice's field

*

are you affected?

  • is your sshd operating on musl? (alpine, openwrt, buildroot, yocto)
  • is it not using pam? alpine's openssh-server doesn't by default, or perchance you set UsePAM no
  • are password logins motionless on? they are by default
  • is there an document alongside fair * as its password? key-only users, ldap users, base on alpine
  • and several other document alongside a genuine password?
  • then that * document takes any password between 257 and 1024 characters

on alpine's authoritative aws and azure images that's the default alpine user, and it has passwordless doas. so it's root

on debian, ubuntu, fedora or item alternatively alongside glibc? going through pam? dropbear? openbsd? you're fine

what now

you

# update. openssh 10.6p2 fixes it. $ apk upgrade openssh # can't update yet? rotate password logins off. $ echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/00-no-passwords.conf $ rc-service sshd restart

one additional thing

did you get hacked? check.

root@your-box

see a row akin that? an document alongside no password fair took a password

if that's the case…

i'm sorry.

you got hacked.

Other Article Hacker News
↑
Close Right Ads
Close Left Ads