Как ограничить пользователей SSH предопределенным набором команд после входа в систему?

88

Это идея для безопасности. Наши сотрудники должны иметь доступ к некоторым командам на сервере Linux, но не ко всем. Например, они должны иметь возможность доступа к файлу журнала ( less logfile) или запускать различные команды ( shutdown.sh/ run.sh).

Исходная информация:

Все сотрудники получают доступ к серверу с одним и тем же именем пользователя: наш продукт работает с «обычными» правами пользователя, «установка» не требуется. Просто разархивируйте его в свой пользовательский каталог и запустите. Мы управляем несколькими серверами, на которых «установлено» наше приложение. На каждой машине есть пользователь johndoe. Нашим сотрудникам иногда требуется доступ к приложению из командной строки для доступа и проверки файлов журнала или для перезапуска приложения вручную. Только некоторые люди будут иметь полный доступ к командной строке.

Мы используем аутентификацию ppk на сервере.

Было бы замечательно, если бы employee1 имел доступ только к файлу журнала, а employee2 также мог бы делать X и т. Д.

Решение: в качестве решения я использую commandвариант, указанный в принятом ответе. Я напишу свой собственный небольшой сценарий оболочки, который будет единственным файлом, который может быть выполнен для некоторых сотрудников. Скрипт предложит несколько команд, которые можно выполнить, но не других. Я буду использовать следующие параметры, authorized_keysкак указано здесь :

command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host

Для нас этого достаточно. Спасибо, сообщество!

Марсель
источник
Стандартной безопасности Linux ACL на основе разрешений недостаточно? Какие дополнительные функции вам нужны?
Джеймс Брэди,
22
Это ужасная идея, Марсель.
Винко Врсалович
14
@Vinko, @PEZ: Я добавил некоторую справочную информацию. Вместо того, чтобы говорить «глупая идея», вы можете дать ценные комментарии. Что, по вашему мнению, лучше?
Марсель
8
Я до сих пор не вижу оправдания тому, что несколько пользователей используют одно и то же имя пользователя.
Eldelshell
3
«Мой собственный небольшой сценарий оболочки»? Звучит довольно опасно. Если вы не являетесь экспертом, вероятно, есть много способов избежать этого до полной оболочки. Я предпочитаю доверять хорошо написанной, отлаженной и поддерживаемой программе (некоторые из них уже упоминались).
bortzmeyer 05

Ответы:

69

Вы также можете ограничить ключи разрешенными командами (в файле authorized_keys).

Т.е. пользователь не будет входить в систему через ssh, а затем будет иметь ограниченный набор команд, а ему будет разрешено выполнять эти команды только через ssh (например, "ssh somehost bin / showlogfile")

HD.
источник
Выглядит интересно. Можно ли определить несколько команд?
Марсель
12
Эта статья дает вам несколько вариантов для нескольких команд с использованием файла authorized_keys: linuxjournal.com/article/8257
Bash,
@ rd834 ...: Большое спасибо. Я думаю, это дало мне "хорошее" решение ... (добавлено к вопросу). Я приму этот ответ как «правильный».
Марсель
11
В книге O'Reilly SSH есть прекрасное объяснение того, как это сделать, включая разрешение нескольких команд путем настройки сценария, который смотрит на переменную среды SSH_ORIGINAL_COMMAND. oreilly.com/catalog/sshtdg/chapter/ch08.html
Alex Dupuy
5
в этом ответе serverfault есть хороший совет о том, как разрешить несколько команд с помощью экспортированной переменной SSH_ORIGINAL_COMMAND.
MattBianco,
33

sshследует rshтрадиции, используя программу оболочки пользователя из файла паролей для выполнения команд.

Это означает, что мы можем решить эту проблему без sshкакого-либо вмешательства в конфигурацию.

Если вы не хотите, чтобы у пользователя был доступ к оболочке, просто замените оболочку этого пользователя сценарием. Если вы посмотрите /etc/passwdвнутрь, то увидите, что есть поле, которое назначает интерпретатор команд оболочки каждому пользователю. Сценарий используется как оболочка как для их интерактивного входа ssh user@host в систему, так и для команд ssh user@host command arg ....

Вот пример. Я создал пользователя foo, оболочка которого представляет собой скрипт. Сценарий печатает сообщение, my arguments are:за которым следуют его аргументы (каждый в отдельной строке и в угловых скобках) и завершается. В журнале на всякий случай аргументов нет. Вот что происходит:

webserver:~# ssh foo@localhost
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.

Если пользователь пытается запустить команду, это выглядит так:

webserver:~# ssh foo@localhost cat /etc/passwd
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>

Наша «оболочка» получает -cвызов стиля со всей командой в качестве одного аргумента точно так же, как/bin/sh ее получении.

Итак, как видите, сейчас мы можем разработать сценарий дальше, чтобы он распознавал случай, когда он был вызван с -cаргументом, а затем анализировал строку (например, путем сопоставления с образцом). Те строки, которые разрешены, можно передать реальной оболочке путем рекурсивного вызова /bin/bash -c <string>. В случае отклонения может быть напечатано сообщение об ошибке и завершено (включая случай, когда -cон отсутствует).

Вы должны быть осторожны, когда пишете это. Я рекомендую писать только положительные совпадения, которые разрешают только очень определенные вещи, и запрещают все остальное.

Примечание: если это так root, вы все равно можете войти в эту учетную запись, переопределив оболочку в suкоманде, как это su -s /bin/bash foo. (Замените оболочку по выбору.) Не-root не может этого сделать.

Вот пример сценария: разрешить пользователю использовать только sshдля gitдоступа к репозиториям в /git.

#!/bin/sh

if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then
  printf "interactive login not permitted\n"
  exit 1
fi

set -- $2

if [ $# != 2 ] ; then
  printf "wrong number of arguments\n"
  exit 1
fi

case "$1" in
  ( git-upload-pack | git-receive-pack )
    ;; # continue execution
  ( * )
    printf "command not allowed\n"
    exit 1
    ;;
esac

# Canonicalize the path name: we don't want escape out of
# git via ../ path components.

gitpath=$(readlink -f "$2")  # GNU Coreutils specific

case "$gitpath" in
  ( /git/* )
     ;; # continue execution
  ( * )
    printf "access denied outside of /git\n"
    exit 1
    ;;
esac

if ! [ -e "$gitpath" ] ; then
   printf "that git repo doesn't exist\n"
   exit 1
fi

"$1" "$gitpath"

Конечно, мы доверяем , что эти программы Git git-upload-packи git-receive-packне имеют отверстий или аварийные люки , которые дают пользователям доступ к системе.

Это заложено в такой схеме ограничений. Пользователь аутентифицирован для выполнения кода в определенном домене безопасности, и мы вводим ограничение, чтобы ограничить этот домен субдоменом. Например, если вы разрешаете пользователю запускать vimкоманду для определенного файла для его редактирования, пользователь может просто получить оболочку с расширением :!sh[Enter].

Каз
источник
6
Серьезно, это ОЧЕНЬ ОПАСНО. Что остановит меня от выполнения git-receive-pack '/git/';dd if=/dev/urandom of=/dev/sda?
Yeti
@Yeti У нас здесь есть отверстие для ввода команд? Это необходимо решить. Кроме того, мне caseне кажется правильным злоупотребление шаблонами файлов, которое я совершил в .
Kaz
1
Да, /bin/bash -c "$2"небезопасно (похоже на то, как работает SQL-инъекция). Вы можете фильтровать строку с помощью «волшебных кавычек», как PHP. Но самый простой способ полностью обеспечить безопасность - это вызвать команду вручную, а затем передать параметры в двойных кавычках. Потому что безопасность всего этого зависит от того, является ли эта команда самым слабым звеном (сложнее проверить). Самое интересное, что у вашего ответа 22 положительных голоса, но этого никто не заметил;) Вы обновите свой ответ?
Yeti
1
@Yeti Да; Я только что сделал. Я заменил сценарий на тот, который прерывает аргумент -c, setа затем берет из него только первые два слова. Первая должна быть разрешенной git-командой, а вторая должна быть каноническим путем, проверенным на соответствие разрешенному префиксу, а также проверенным на наличие. Вы можете придумать способ сломать это?
Kaz
1
Если кто-то не создает псевдоним (или не отменяет команду) для любой из данных команд, то нет, двойные кавычки Bash должны быть безопасными (а если нет, то это ошибка в Bash).
Yeti
15

То, что вы ищете, называется Restricted Shell . Bash предоставляет такой режим, в котором пользователи могут выполнять только команды, имеющиеся в их домашних каталогах (и они не могут перемещаться в другие каталоги), что может быть достаточно для вас.

Я нашел эту ветку очень показательной, хотя и немного устаревшей.

Винко Врсалович
источник
1
Что, если пользователь введет "! / Bin / sh" или что-то подобное из приглашения less?
PEZ
3
@Ubersoldat: Пожалуйста, повзрослейте и уменьшите агрессию во всех своих постах. Он спрашивал, применяется ли ограничение только к bash или дочерним процессам (и, чтобы ответить на его вопрос, оказалось, что это не так).
Основная проблема с ограниченной оболочкой заключается в том, что для ее защиты вы должны использовать .profile или .bashrc для ограничения PATH, отключения встроенных функций и т. Д., Но эти файлы вызываются только для интерактивных оболочек. Если пользователь использует ssh для запуска удаленной команды, они не вызываются. Это позволяет пользователю с доступом ssh к учетной записи с SHELL = / bin / rbash просто делать что-то вроде "ssh remotehost bash", чтобы получить неинтерактивную, но неограниченную оболочку. Вам нужны принудительные команды SSH, как предлагалось HD, но это может защитить от экранирования оболочки, как запрашивает PEZ (после блокировки PATH - по умолчанию он включает / bin: / usr / bin).
Alex Dupuy
2
Я беру это обратно, bash будет вызывать .bashrc (не .profile) при работе в неинтерактивном режиме под sshd; однако вы должны убедиться, что вы явно задали PATH и отключили встроенные функции и псевдонимы в .bashrc - изменение на подкаталог не в / выше PATH или .ssh / или .bashrc также является хорошей идеей. Наличие любой команды, которая может записывать в произвольные файлы, создаст проблему - это не всегда очевидно, например, команда sed 'w' может использоваться для перезаписи .bashrc и выхода из строя. Chroot jail всегда будет безопаснее, если вы можете его использовать, а принудительные команды ssh будут более ограниченными.
Alex Dupuy
5

Почему бы вам не написать свою собственную оболочку входа в систему? Было бы довольно просто использовать для этого Bash, но вы можете использовать любой язык.

Пример в Bash

Используйте свой любимый редактор для создания файла /root/rbash.sh(это может быть любое имя или путь, но должно быть chown root:rootи chmod 700):

#!/bin/bash

commands=("man" "pwd" "ls" "whoami")
timestamp(){ date +'%Y-%m-%s %H:%M:%S'; }
log(){ echo -e "$(timestamp)\t$1\t$(whoami)\t$2" > /var/log/rbash.log; }
trycmd()
{
    # Provide an option to exit the shell
    if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]]
    then
        exit
        
    # You can do exact string matching for some alias:
    elif [[ "$ln" == "help" ]]
    then
        echo "Type exit or q to quit."
        echo "Commands you can use:"
        echo "  help"
        echo "  echo"
        echo "${commands[@]}" | tr ' ' '\n' | awk '{print "  " $0}'
    
    # You can use custom regular expression matching:
    elif [[ "$ln" =~ ^echo\ .*$ ]]
    then
        ln="${ln:5}"
        echo "$ln" # Beware, these double quotes are important to prevent malicious injection
        
        # For example, optionally you can log this command
        log COMMAND "echo $ln"
    
    # Or you could even check an array of commands:
    else
        ok=false
        for cmd in "${commands[@]}"
        do
            if [[ "$cmd" == "$ln" ]]
            then
                ok=true
            fi
        done
        if $ok
        then
            $ln
        else
            log DENIED "$cmd"
        fi
    fi
}

# Optionally show a friendly welcome-message with instructions since it is a custom shell
echo "$(timestamp) Welcome, $(whoami). Type 'help' for information."

# Optionally log the login
log LOGIN "$@"

# Optionally log the logout
trap "trap=\"\";log LOGOUT;exit" EXIT

# Optionally check for '-c custom_command' arguments passed directly to shell
# Then you can also use ssh user@host custom_command, which will execute /root/rbash.sh
if [[ "$1" == "-c" ]]
then
    shift
    trycmd "$@"
else
    while echo -n "> " && read ln
    do
        trycmd "$ln"
    done
fi

Все, что вам нужно сделать, это установить этот исполняемый файл в качестве оболочки для входа. Например, отредактируйте /etc/passwdфайл и замените текущую оболочку входа этого пользователя /bin/bashна /root/rbash.sh.

Это всего лишь простой пример, но вы можете сделать его настолько продвинутым, насколько захотите, идея есть. Будьте осторожны, чтобы не заблокировать себя, изменив собственную оболочку входа в систему и единственный пользователь. И всегда проверяйте странные символы и команды, чтобы убедиться, что это действительно безопасно.

Вы можете проверить его: su -s /root/rbash.sh.

Остерегайтесь , убедитесь, что соответствует вся команда, и будьте осторожны с подстановочными знаками! Лучше исключить Bash-символы , такие как ;, &, &&, ||, $, и обратные кавычки , чтобы быть уверенным.

В зависимости от свободы, которую вы даете пользователю, не будет намного безопаснее, чем эта. Я обнаружил, что часто мне нужно было создать пользователя, у которого есть доступ только к нескольким соответствующим командам, и в этом случае это действительно лучшее решение. Однако если вы хотите дать больше свободы, тюрьма и разрешения могут быть более подходящими. Ошибки совершаются легко, и замечают их только тогда, когда уже слишком поздно.

Йети
источник
Мне такой подход очень понравился. Вы хоть представляете, как мы можем обрабатывать многословные команды, такие как «перезапуск службы httpd»?
Farzan
2
@Farzan Вы можете выполнять команды в переменной, например ln="service httpd restart", с: ${ln[@]}. Тем не менее, не забудьте подумать о проблемах безопасности, в таком случае будет полезен белый список только для буквенно-цифровых символов и пробелов. Но вы также можете просто делать: if [[ "$ln" == "restart-httpd"];then service httpd restart;fiи работать с такими простыми командами.
Yeti
/root/rbash.sh: Permission denied Я тоже пробовал chmod 777
Christian
@Christian, вы добавили /root/rbash.shк /etc/shells? Это зависит от дистрибутива. Вы также можете попробовать временно отключить selinuxи проверить сообщения журнала на предмет подсказок (посмотрите на метку времени) в файлах в /var/log.
Yeti
@yeti нет, объяснили добавить в / root :) Сейчас попробую.
Christian
4

Вы должны приобрести rssh, ограниченную оболочку

Вы можете следовать руководствам по ограничениям, упомянутым выше, все они не требуют пояснений и просты в использовании. Понять термины `chroot jail ', как эффективно реализовать конфигурации sshd / терминала и т. Д.

Поскольку большинство ваших пользователей получают доступ к вашим терминалам через sshd, вам также, вероятно, следует изучить sshd_conifg, файл конфигурации демона SSH, чтобы применить определенные ограничения через SSH. Однако будьте осторожны. Правильно поймите, что вы пытаетесь реализовать, поскольку последствия неправильной конфигурации, вероятно, весьма ужасны.

Чуах
источник
1
Обратите внимание, что pizzashack.org/rssh - отличное (возможно, лучшее) решение для особого случая, когда вы хотите разрешить scp / sftp / rdist / rsync / cvs (и вам не нужен доступ к чему-либо за пределами chroot jail), однако , это не решает общий вопрос первоначального автора, который хотел, чтобы пользователи могли просматривать файлы журнала и запускать определенные сценарии запуска / завершения работы.
Alex Dupuy
2
rsshбыл удален из Debian Buster. Я думаю, что новая популярность - это спешка с GNU .
Thomas
1
@Thomas Я считаю, что rssh теперь не обслуживается и имеет известную проблему безопасности: sourceforge.net/p/rssh/mailman/message/36519118
Макс Барраклаф,
2

GNU Rush может быть наиболее гибким и безопасным способом добиться этого:

GNU Rush - это пользовательская оболочка с ограниченным доступом, предназначенная для сайтов, которые предоставляют ограниченный удаленный доступ к своим ресурсам, например репозиториям svn или git, scp и т. П. Используя сложный файл конфигурации, GNU Rush дает вам полный контроль над командными строками, выполняемыми пользователями, а также над использованием системных ресурсов, таких как виртуальная память, время процессора и т. Д.

Томас
источник
1

Вы можете посмотреть на создание тюрьмы .

tmeisenh
источник
Вопрос помечен как "linux". Разве тюрьмы не специфичны для FreeBSD?
Макс Барраклаф
0

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

Еще одна вещь, на которую стоит обратить внимание, - это PolicyKit .

Вам придется немного погуглить, чтобы все заработало, поскольку в данный момент это определенно не является сильной стороной Linux.

Брайан Ребейн
источник
0

[Раскрытие: я написал sshdo, описанный ниже]

Если вы хотите, чтобы логин был интерактивным, то, вероятно, правильным ответом будет установка оболочки с ограниченным доступом. Но если есть реальный набор команд, которые вы хотите разрешить (и ничего больше), и эти команды можно выполнять индивидуально через ssh (например, ssh user @ host cmd arg blah blah), тогда общий белый список команд для управления ssh может быть тем, что вам нужно. Это полезно, когда команды каким-то образом написаны на стороне клиента и не требуют от пользователя ввода команды ssh.

Для этого есть программа sshdo. Он контролирует, какие команды могут быть выполнены через входящие ssh-соединения. Его можно скачать по адресу:

http://raf.org/sshdo/ (прочтите справочные страницы здесь) https://github.com/raforg/sshdo/

У него есть режим обучения, позволяющий выполнять все попытки выполнения команд, и параметр --learn для создания конфигурации, необходимой для постоянного разрешения изученных команд. После этого режим тренировки можно выключить, и никакие другие команды выполняться не будут.

У него также есть опция --unlearn, чтобы запретить выполнение команд, которые больше не используются, чтобы поддерживать минимальные привилегии, поскольку требования меняются с течением времени.

Он очень требователен к тому, что позволяет. Это не позволит команду с любыми аргументами. Могут быть разрешены только полные команды оболочки.

Но он поддерживает простые шаблоны для представления подобных команд, которые различаются только цифрами, которые появляются в командной строке (например, порядковые номера или отметки даты / времени).

Это похоже на брандмауэр или белый список для команд ssh.

И он поддерживает разные команды, разрешенные для разных пользователей.

раф
источник