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
. (Замена оболочки по выбору.) Некорневые пользователи не могут этого сделать.
Вот пример сценария: ограничить пользователя только использованием 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]
.