Як обмежити користувачів SSH попередньо визначеним набором команд після входу?


85

Це ідея для цінного паперу. Наші співробітники повинні мати доступ до деяких команд на сервері Linux, але не до всіх. Вони, наприклад, повинні мати можливість отримати доступ до файлу журналу ( less logfile) або запускати різні команди ( shutdown.sh/ run.sh).

Довідкова інформація:

Усі співробітники отримують доступ до сервера з однаковим іменем користувача: Наш продукт працює із "звичайними" дозволами користувача, ніякого "встановлення" не потрібно. Просто розпакуйте його в папці користувача та запустіть. Ми управляємо кількома серверами, де "встановлено" наш додаток. На кожній машині є користувач johndoe. Нашим працівникам іноді потрібен доступ до програми в командному рядку для доступу та перевірки файлів журналів або для ручного перезапуску програми. Лише деякі люди мають повний доступ до командного рядка.

Ми використовуємо аутентифікацію ppk на сервері.

Було б чудово, якби співробітник1 мав доступ лише до журналу, а працівник2 також міг робити 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
Це жахлива ідея, Марселе.
Вінко Врсалович

13
@Vinko, @PEZ: Я додав деякі довідкові відомості. Замість того, щоб говорити "дурна ідея", ви можете надати коментарі з цінністю. Що, на вашу думку, є кращою ідеєю?
Марсель

8
Я все ще не бачу виправдання того, що кілька користувачів мають одне і те ж ім'я користувача.
Eldelshell

3
"Мій власний маленький сценарій оболонки"? Це звучить досить небезпечно. Якщо ви не фахівець, існує, мабуть, багато способів врятуватися від нього до повної оболонки. Я б скоріше довірився добре написаній, налагодженій та підтриманій програмі (кілька з них були згадані).
bortzmeyer

Відповіді:


68

Ви також можете обмежити ключі допустимими командами (у файлі санкціонованих ключів).

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


Це виглядає цікаво. Чи можна визначити кілька команд?
Марсель

12
У цій статті ви знайдете кілька варіантів декількох команд із використанням файлу санкціонованих ключів
Bash

@ rd834 ...: Велике спасибі. Я думаю, це дало мені "хороше" рішення ... (додано до запитання). Я прийму цю відповідь як "правильну".
Марсель 02

11
У книзі O'Reilly SSH є чудове пояснення того, як це зробити, включаючи можливість декількох команд шляхом налаштування сценарію, який переглядає змінну середовища SSH_ORIGINAL_COMMAND. oreilly.com/catalog/sshtdg/chapter/ch08.html
Alex Dupuy

5
у цій відповіді за замовчуванням є приємна порада щодо дозволу декількох команд за допомогою експортованої змінної SSH_ORIGINAL_COMMAND.
MattBianco

32

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].


6
Серйозно, це ДУЖЕ НЕБЕЗПЕЧНО. Що зупинить мене від виконання git-receive-pack '/git/';dd if=/dev/urandom of=/dev/sda?
Yeti

@Yeti У нас тут є отвір для введення команд? Це потрібно вирішити. Крім того, зловживання шаблонами файлів, яке я вчинив, caseне здається мені правильним.
Каз

1
Так, /bin/bash -c "$2"є небезпечним (подібно до того, як працює ін’єкція SQL). Ви можете відфільтрувати рядок за допомогою "магічних лапок", таких як PHP. Але найпростіший спосіб абсолютно забезпечити безпеку - викликати команду вручну, а потім передавати параметри в подвійні лапки. Оскільки безпека всього цього тоді залежить від того, яка команда є найслабшим ланкою (важче перевірити). Найцікавіше побачити, як ваша відповідь має 22 голоси проти, але цього ніхто не помітив;) Чи оновите ви власну відповідь?
Yeti

1
@Yeti Так; Я тільки що зробив. Я замінив сценарій на той, який розбиває аргумент -c, setа потім бере з нього лише перші два слова. Перша повинна бути дозволеною git-командою, а друга - шляхом, який канонізується, перевіряється з дозволеним префіксом, а також перевіряється на існування. Чи можете ви придумати будь-який спосіб це зламати?
Kaz

1
Якщо хтось не створить псевдонім (або не замінить команду) для будь-якої із заданих команд, тоді ні, подвійні лапки Bash повинні бути безпечними (а якщо ні, то це помилка в Bash).
Yeti

15

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

Я знайшов цю тему дуже ілюстративною, хоча б трохи застарілою.


1
Що робити, якщо користувач робить "! / Bin / sh" або щось подібне з менш підказки?
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 завжди буде безпечнішою, якщо ви зможете користуватися нею, а примусові команди ssh будуть більш обмеженими.
Alex Dupuy,

4

Ви повинні придбати `rssh ', обмежену оболонку

Ви можете слідувати згаданим вище вказівкам щодо обмежень, всі вони досить зрозумілі та прості у виконанні. Зрозумійте терміни `` в'язниця chroot '', і як ефективно реалізувати конфігурації sshd / терміналу тощо.

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


1
Зверніть увагу, що pizzashack.org/rssh - відмінне (можливо, найкраще) рішення для особливого випадку, коли ви хочете дозволити scp / sftp / rdist / rsync / cvs (і не потребують доступу до нічого поза в'язницею chroot) - однак , це не вирішує загального питання про оригінальний плакат, який хотів, щоб користувачі мали змогу переглядати файли журналів та запускати певні сценарії запуску / вимкнення.
Alex Dupuy,

2
rsshбуло видалено з Debian Buster. Я думаю, що нова гарячість - це пік GNU .
Томас

1
@Thomas Я вважаю, що rssh зараз не підтримується і має відому проблему безпеки: sourceforge.net/p/rssh/mailman/message/36519118
Макс

4

Чому б вам не написати власну оболонку для входу? Використовувати 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"?
Фарзан

2
@Farzan Ви можете виконувати команди у змінній, наприклад ln="service httpd restart", з: ${ln[@]}. Тим не менше, не забудьте подумати про проблеми безпеки, у такому випадку корисним буде білий список лише для буквено-цифрових символів та пробілів. Але ви також можете просто зробити:, if [[ "$ln" == "restart-httpd"];then service httpd restart;fiі працювати з такими простими командами.
Єті

/root/rbash.sh: Permission denied Я також спробував chmod 777
Крістіан

@Christian, ти додав /root/rbash.shдо /etc/shells? Це залежить від розподілу. Ви також можете спробувати тимчасово відключити selinuxта перевірити повідомлення журналу на наявність підказок (подивіться на позначку часу) у файлах у /var/log.
Єті

@yeti ні, пояснили, що потрібно додати до / root :) Спробую зараз.
Крістіан


1

GNU Rush може бути найбільш гнучким і безпечним способом досягнення цього:

GNU Rush - це обмежена користувацька оболонка, призначена для сайтів, які надають обмежений віддалений доступ до своїх ресурсів, таких як репозиторії svn або git, scp тощо. Використовуючи складний файл конфігурації, GNU Rush дає вам повний контроль над командними рядками, які виконують користувачі, а також над використанням системних ресурсів, таких як віртуальна пам'ять, час процесора тощо.


0

Інший спосіб дивитись на це - використання POSIX ACL, він повинен підтримуватися вашою файловою системою, однак ви можете мати чітке налаштування всіх команд у 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.

І він підтримує різні команди, дозволені для різних користувачів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.