xorl %eax, %eax

NetBSD-SA2009-004: OpenPAM passwd(1) changing weakness

leave a comment »

This critical vulnerability was disclosed by NetBSD Project on 22 June 2009 and affects NetBSD up to 14 June 2009 NetBSD-current release. The bug was discovered by Thomas Getzke and reported by Hubert Feyrer. The final fix was written by Tonnerre Lombard as you can read in the official advisory. Here is the code as seen at src/lib/libpam/modules/pam_unix/pam_unix.c.

/*
 * password management
 *
 * standard Unix and NIS password changing
 */
PAM_EXTERN int
/*ARGSUSED*/
pam_sm_chauthtok(pam_handle_t *pamh, int flags,
    int argc __unused, const char *argv[] __unused)
{
	struct passwd *pwd, new_pwd, old_pwd;
	login_cap_t *lc;
	const char *user, *passwd_db, *new_pass, *old_pass, *p;
	int retval, tries, min_pw_len = 0, pw_expiry = 0;
	char salt[_PASSWORD_LEN+1];
	char old_pwbuf[1024];
   ...
	if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) {
		if ((user = getlogin()) == NULL) {
   ...
	/*
	 * Determine which password type we're going to change, and
	 * remember it.
	 *
	 * NOTE: domain does not need to be freed; its storage is
	 * allocated statically in libc.
	 */
	passwd_db = openpam_get_option(pamh, "passwd_db");
   ...
		if (strcmp(passwd_db, "files") == 0) {
			if (getuid() == 0) {
				/* Root doesn't need the old password. */
				return (pam_set_item(pamh, PAM_OLDAUTHTOK, ""));
			}
		}

		if (pwd->pw_passwd[0] == '') {
			/*
			 * No password case.
			 * XXX Are we giviing too much away by not prompting
			 * XXX for a password?
			 * XXX Check PAM_DISALLOW_NULL_AUTHTOK
			 */
			return (pam_set_item(pamh, PAM_OLDAUTHTOK, ""));
		} else {
   ...
		/* Get the new password. */
		for (tries = 0;;) {
			pam_set_item(pamh, PAM_AUTHTOK, NULL);
   ...
		new_pwd = old_pwd;
		pwd = &new_pwd;
		pwd->pw_passwd = crypt(new_pass, salt);
		pwd->pw_change = pw_expiry ? pw_expiry + time(NULL) : 0;
   ...
	return (PAM_ABORT);
}

PAM_MODULE_ENTRY("pam_unix");

This is pretty much the code path when changing a password on a PAM enabled NetBSD system. Thomas Getzke noticed that there is no limitation for unprivileged users to change the root’s password since there is no check on whether the passwd structure belogs to root or not. This could be easily abused by executing a command similar to: passwd root
Of course, this affects systems that use PAM UNIX authentication. To fix this, the following patch was applied.

                                /* Root doesn't need the old password. */
                                return (pam_set_item(pamh, PAM_OLDAUTHTOK, ""));
                        }
+                       /*
+                        * Apparently we're not root, so let's forbid editing
+                        * root.
+                        * XXX Check for some flag to indicate if this
+                        * XXX is the desired behavior.
+                        */
+                       if (pwd->pw_uid == 0)
+                               return (PAM_PERM_DENIED);
                }

Which adds the missing check and returns the equivalent PAM permission denied if regular users attempt to change root’s password.

Written by xorl

June 23, 2009 at 20:27

Posted in bugs, netbsd

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s