Gentle ping. Patch available. Tar does not attempt to initialize supplementary groups when dropping privileges. Also according to this https://wiki.sei.cmu.edu/confluence/display/c/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges git should be reseted before uid.
diff --git a/lib/system.h b/lib/system.h index e7f531c..97983b7 100644 --- a/lib/system.h +++ b/lib/system.h @@ -480,7 +480,8 @@ char *getenv (); # define TTY_NAME "/dev/tty" # define sys_reset_uid_gid() \ do { \ - if (! (setuid (getuid ()) == 0 && setgid (getgid ()) == 0)) \ + if (! (initgroups( getenv("USER"), getgid ()) == 0 && \ + setgid (getgid ()) == 0 && setuid (getuid ()) == 0)) \ abort (); \ } while (0) #endif On Mon, Jan 18, 2021 at 12:22 PM Ondrej Dubaj <odu...@redhat.com> wrote: > When tar executes remote command for remote archive (by default > /usr/bin/ssh), it calls sys_reset_uid_gid in rmt_open__ in forked child right > before execl. So it seems like the intent in set-uid/set-gid situations is to > run the remote command with the privileges of the invoking user, not with the > elevated privileges. > > The sys_reset_uid_gid is defined in lib/system.h as > > # define sys_reset_uid_gid() \ > do { \ > if (! (setuid (getuid ()) == 0 && setgid (getgid ()) == 0)) \ > abort (); \ > } while (0) > > This code means that supplementary groups are not cleared and saved > set-group-ID is not reset. > > Affected version: tar-1.32 > > > Steps to Reproduce: > 1. Prepare "remote command" to display privileges of the process on standard > error output -- create /usr/local/bin/id with content > > #!/bin/bash -p > /usr/bin/id >&2 > > 2. Make it executable: chmod +x /usr/local/bin/id > 3. Create test program suid-tar-with-groups.c to be run as set-uid/set-gid > which also sets some supplementary groups: > > #include <sys/types.h> > #include <unistd.h> > #include <grp.h> > #include <stdlib.h> > > int main(void) { > const gid_t list[] = { 992, 993 }; > setgroups(2, list); > execl("/usr/bin/tar", "tar", "-c", "--rsh-command=/usr/local/bin/id", > "-f", "root@localhost:/tmp/out.tar", "/something/somewhere", (char *) NULL); > } > > 4. Build it as root: gcc -o /usr/local/bin/suid-tar-with-groups > suid-tar-with-groups.c > 5. Make it set-uid/set-gid as root: chmod ug+s > /usr/local/bin/suid-tar-with-groups > 6. Have a non-privileged account which has no supplemental groups: run id to > check: > uid=1000(test) gid=1000(test) groups=1000(test) > context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 > 7. From this account, execute: /usr/local/bin/suid-tar-with-groups > > Actual results: > > uid=1000(test) gid=1000(test) groups=1000(test),992(chrony),993(unbound) > context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 > tar: root@localhost\:/tmp/out.tar: Cannot open: Input/output error > tar: Error is not recoverable: exiting now > > Expected results: > > uid=1000(test) gid=1000(test) groups=1000(test) > context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 > tar: root@localhost\:/tmp/out.tar: Cannot open: Input/output error > tar: Error is not recoverable: exiting now > > Additional info: > > This demonstrates that when tar drops the privileges back to the invoking > real uid and real gid to execute the remote command, the process still has > the extra supplementary groups of that set-uid process. > > Based on > https://wiki.sei.cmu.edu/confluence/display/c/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges, > calling setgroups() before setuid is needed. I tried with plain setgroups(0, > NULL); added at the start of sys_reset_uid_gid that the supplementary groups > will be purged. > > Another issue is the order of the setuid() and setgid() -- since > sys_reset_uid_gid does setuid first, by the time it runs setgid, the process > no longer has permissions to drop the saved set-group-ID. The reproducer > above does not demonstrate this second problem specifically, let's just say > the order should be reversed. > > Regards, > > Ondrej Dubaj > >