Bug 2909 - sshd segfaults on non-existent users when there is an NIS ngetgroup included in /etc/passwd
Summary: sshd segfaults on non-existent users when there is an NIS ngetgroup included ...
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 7.7p1
Hardware: ix86 Linux
: P5 normal
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks: V_8_0
  Show dependency treegraph
 
Reported: 2018-09-26 00:25 AEST by Todd Eigenschink
Modified: 2021-03-04 09:54 AEDT (History)
1 user (show)

See Also:


Attachments
segfault test program (2.17 KB, text/x-csrc)
2018-09-26 00:25 AEST, Todd Eigenschink
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Todd Eigenschink 2018-09-26 00:25:28 AEST
Created attachment 3181 [details]
segfault test program

We might have a bit of an odd/old configuration, but it works otherwise.

We get lots and lots of these. This is the only machine whose sshd is exposed to the internet:

Sep 25 09:42:53 pluto kernel: sshd[1871]: segfault at 0 ip 005023ac sp 7f899810 error 4 in sshd[49b000+6d000]

Normal users here can log in fine, so I figured it was just trash the password-searchers were throwing at sshd. I finally took some time to dig in to it. It turns out that trying to ssh in as an invalid user (ssh foo@pluto) causes sshd to segfault as soon as I enter the password.

Once I could duplicate it at will it was pretty easy to chase down. The pick_salt() function iterates through users with getpwent() looking for a salt it can use. Our setup doesn't use shadow passwords, so it doesn't find what it's looking for. When it gets to the end of the password file, the last line is "+@users" to add in our NIS user netgroup.

shadow_pw() can't find a password in that line, so it returns NULL, which pointer is them immediately dereferenced.

I extracted the relevant code into a standalone program that demonstrates the problem, attached. (I used entire functions; I didn't pare it down to absolute bare minimum--but there are only three functions.) When I run it on this system, it produces the following output:

pw = 77efacc0
pw_name = '+@users'
  passwd = '(null)'
Segmentation fault



This small change takes care of it:

--- openssh-7.8p1/openbsd-compat/xcrypt.c.orig	2018-08-23 01:41:42.000000000 -0400
+++ openssh-7.8p1/openbsd-compat/xcrypt.c	2018-09-25 10:11:11.639816915 -0400
@@ -83,7 +83,7 @@
 	setpwent();
 	while ((pw = getpwent()) != NULL) {
 		passwd = shadow_pw(pw);
-		if (passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) {
+		if (passwd && passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) {
 			typelen = p - passwd + 1;
 			strlcpy(salt, passwd, MIN(typelen, sizeof(salt)));
 			explicit_bzero(passwd, strlen(passwd));



We compile --prefix=/usr --without-shadow.

We're running 7.8p1 now. This problem predates 7.8, though; I'm not sure how far back it goes.
Comment 1 Damien Miller 2018-10-10 14:59:09 AEDT
Thanks - i've committed a similar fix.

commit d1d301a1dd5d6cc3a9ed93ab7ab09dda4cb456e0 (HEAD -> master, origin/master, origin/HEAD)
Author: Damien Miller <djm@mindrot.org>
Date:   Wed Oct 10 14:57:00 2018 +1100

    in pick_salt() avoid dereference of NULL passwords
    
    Apparently some NIS implementations can leave pw->pw_passwd (or the
    shadow equivalent) NULL.
    
    bz#2909; based on patch from Todd Eigenschink
Comment 2 Damien Miller 2018-10-19 17:13:34 AEDT
Retarget unfinished bugs to OpenSSH 8.0
Comment 3 Damien Miller 2018-10-19 17:14:43 AEDT
Retarget unfinished bugs to OpenSSH 8.0
Comment 4 Damien Miller 2018-10-19 17:15:47 AEDT
Retarget unfinished bugs to OpenSSH 8.0
Comment 5 Damien Miller 2019-02-08 15:01:11 AEDT
this was fixed a while back
Comment 6 Damien Miller 2021-03-04 09:54:01 AEDT
close bugs that were resolved in OpenSSH 8.5 release cycle