I have here a script called rwog
(run without groups) that allow a user to run a shell without particular group memberships. rwog
, in more detail...
- Is primarily for a support staffer to pretend to be an ordinary user without
su
-ing to anybody. - Must be run as
root
, but those allowed to run it will be given an entry in/etc/sudoers
. - Should be executed as
sudo rwog groups to drop
. - Will have a
uid
ofroot
, agid
ofthe_support_team
, and permissions0550
(i.e. user and group can read and execute, world can do nothing, and nosetgid
/setuid
bits). - Cannot change your
gid
, change youruid
, or add yourself to supplementary groups. - Revokes pretty much all capabilities, though this may be a tad zealous.
- Does not modify
/etc/group
(soid
will be changed, butid $USER
will not). - Is primarily (but not exclusively) intended to run on a Centos 7 environment..
My main concern: Can this script be exploited to gain escalated privileges? I won't ignore suggestions not related to security.
The Script
#!/bin/bash
function help(){
echo "rwog - run without groups";
echo "Runs a shell as if you weren't in certain supplementary groups."
echo "Good for pretending that you're not a support user."
echo "Usage example:";
echo -e "\trwog [(-h|--help)] [group ...]";
echo "Options:";
echo -e "\t-h or --help: Displays this information.";
exit 1;
}
# Declare vars. Flags initalizing to 0.
# Execute getopt
ARGS=$(getopt -o "h" -l "help" -n "rwog" -- "$@");
#Bad arguments
if [ $? -ne 0 ];
then
help;
fi
eval set -- "$ARGS";
while true; do
case "$1" in
-h|--help)
shift;
help;
;;
--)
shift;
break;
;;
esac
done
if [[ $(id -u) != 0 ]]; then
# If you're not root...
echo "You must be root to use this script. Run it with sudo."
exit 1
fi
for group in $@; do
# For each group we want to drop...
if [[ "$group" == "$SUDO_USER" ]]; then
# If you're trying to drop your own gid...
echo "You cannot drop your own gid."
exit 1
elif ! getent group "$group" &>/dev/null ; then
#If this group doesn't exist...
echo "$group is not a valid group."
exit 1
elif ! groups "$SUDO_USER" | grep -E &>/dev/null "\b$group\b"; then
# Else if you're not actually a member of this group...
echo "Not a member of $group, cannot drop it"
exit 1
fi
done
my_groups=$(id -Gn "$SUDO_USER" | xargs -n1 | sort -u)
groups_to_drop=$(echo $@ | xargs -n1 | sort -u)
# Put the groups that you want to drop on multiple lines, then sort them
if [[ -z "$groups_to_drop" ]]; then
# If you didn't pick a group to drop...
echo "Please specify at least one supplementary group to drop."
help
fi
reduced_groups=$(comm -13 <(echo "$groups_to_drop") <(echo "$my_groups") | paste -s -d,)
# Subtract the groups we want to drop from the groups we're in, then merge them onto one line
export USERNAME="$SUDO_USER"
export USER="$SUDO_USER"
export LOGNAME="$SUDO_USER"
export HOME=$( getent passwd "$SUDO_USER" | cut -d: -f6 )
dropped_capabilities=$(capsh --print | grep -E "Bounding set =(.+)" | sed "s/Bounding set =//g")
capsh --secbits=0xf --drop="$dropped_capabilities" --groups="$reduced_groups" --gid="$SUDO_GID" --uid="$SUDO_UID" -- --login
sg
andnewgrp
don't already have support for changing supplementary groups. \$\endgroup\$