Bash-скрипт, чтобы временно запустить оболочку без определенных группах


У меня вот такой скрипт rwog (РООН шйоут граупс), которые позволяют пользователю для запуска оболочки без особых группах. rwogболее подробно...

  • В первую очередь для поддержки сотрудник притвориться обычным пользователем, без su-Инг никому.
  • Должна выполняться как rootно те позволили запустить его будет предоставлена запись в /etc/sudoers.
  • Должен быть выполнен как sudo rwog groups to drop.
  • Будет uid из root, а gid из the_support_teamи разрешения 0550 (т. е. пользователь и группа могут читать и исполнять, мир не может сделать ничего, и нет setgid/setuid бит).
  • Не можете изменить gidизмените свой uidили добавить себе дополнительных групп.
  • Отменяет почти все функции, хотя это может быть немного одержимым.
  • Не изменяет /etc/group (так id будет изменен, но id $USER не будет).
  • В первую очередь (но не исключительно), предназначенные для запуска на CentOS 7 среда..

Моя главная забота: может ли этот сценарий быть использована для получения повышенными привилегиями? Я не игнорирую предложения, не связанные с безопасностью.

Сценарий

#!/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


Комментарии
2 ответа

Это не ошибка, чтобы попросить о помощи

Когда -h пройден, help() функция не завершает свою работу с ненулевым статусом, потому что он сделал то, что попросили.

И наоборот, когда мы передаем никакие аргументы, мы должны выйти с ненулевым, и мы должны написать сообщение в стандартный поток ошибок.

Я напишу, что как

help() {
local tab=$'\t'
cat <<END
$0 - run without groups
Runs a shell as if you weren't in certain supplementary groups.
Good for pretending that you're not a support user.
Usage example:
${tab}$0 [(-h|--help)] [group ...]
Options:
${tab}-h or --help: Displays this information.
END
}

И затем использовать его в качестве

# Just use the command directly instead of testing $?
if ! ARGS=$(getopt -o "h" -l "help" -n "rwog" -- "$@");
then
help >&2
exit 1
fi

и

    case "$1" in
-h|--help)
help
exit 0
;;

В другом месте в коде, диагностические сообщения печатаются на стандартный вывод; они должны быть перенаправлены на &2.

Проверка более покинуть статусы

Мы зависим от таких инструментов, как xargs и sort которые могут и не присутствовать. Подумайте, позволяя Баш проверить некоторые статусы, но убедитесь, что вы знаете, какие команды это не будет проверять:

set -e

Также рассмотреть возможность получения Bash для проверки, что вы не используете неопределенные переменные:

set -u

Вы будете хотеть использовать расширения, такие как ${foo:-} когда вам нужно, чтобы избежать этой проверки.

Цитата переменной, разложения

Просто потому, что вы проверили, что это выполняется с помощью корня (возможно, перебор - это достаточно для того, чтобы любой пользователь, который может работать capsh?), это не значит, что они не могут сделать что-то неожиданное. Так что пишите "$@"не $@:

for group in "$@"; do

Не сравнивайте группу от пользователя

if [[ "$group" == "$SUDO_USER" ]]; then

Ты имел в виду "$SUDO_GID" там? Кроме того, есть небольшой пункт с использованием как [[...]] а цитаты - я бы поставил на портативный [...] здесь.

Если ты имеешь в виду Для сравнения с именем пользователя (например, вы знаете, ваши настройки всегда создает для каждого пользователя группы с одинаковыми фамилиями), то его хорошая идея, чтобы добавить комментарий, констатировав, что предположение, как это может не работать на другой системе вы скопируйте это.

Не нужно grep и sed в трубопроводе

СЭД вполне способен выбирать линии:

dropped_capabilities=$(capsh --print | sed -n -e 's/Bounding set =//gp')

Позаботиться с $PATH

Хотя на вашем сайте sudo политика должна сдерживать PATHэто может быть хорошей идеей, чтобы установить определенный PATH в начале скрипта и/или использовать полное имя пути для исполняемых файлов.

8
ответ дан 5 марта 2018 в 05:03 Источник Поделиться

Некоторые второстепенные моменты, на вершине прекрасный обзор Тоби.

Проверка ввода

Эта проверка должна быть перенесена в код:


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

Это происходит после for group in $@после my_groups создается, и после groups_to_drop создается из $@. Проверить на Ли $@ пустой должны прийти до всех этих операций.

Совет: вместо for group in "$@"; doвы могли бы написать for group; do к такому же эффекту.

Стиль

В первой половине сценария,
многие строки заканчиваются резервные ;. Удалить эти.

2
ответ дан 7 марта 2018 в 08:03 Источник Поделиться