Forced command в SSH: запуск только одной команды без доступа к оболочке
Приветствую!

В этой заметке мы рассмотрим механизм “Forced command” в SSH, который позволяет ограничить SSH-ключи выполнением одной команды.

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

Данный механизм используется для:

В недавней статье про то, как поднять свой статический сайт с помощью Hugo, я использовал данный приём с SSH, чтобы инициировать запуск деплой скрипта на Bash.

Т.к. тема интересная, решил сделать отдельную заметку с примерами👨‍💻.

Подготовка на клиенте - desktop.lan

Сперва определим вводные данные:

KeyValue
Серверtest.r4ven.me
Клиентdesktop.lan
Пользовательivan

На клиентской машине генерируем новый ключ SSH:

BASH
ssh-keygen -q -N "" -t ed25519 -f ~/.ssh/id_ed25519_test
Нажмите, чтобы развернуть и увидеть больше

В данном случае, ключи будут сохранены в директории ~/.ssh под именами id_ed25519_test (приватный) и id_ed25519_test.pub (публичный).

Выведем в терминал публичную часть нашего ключа, ту что с суффиксом .pub:

BASH
cat ~/.ssh/id_ed25519_test.pub
Нажмите, чтобы развернуть и увидеть больше

Получите строку вида:

id_ed25519_test.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXsCuHrzzbYmJXJqeui8j78pkYf+VbYuGeX8iK/W0EW ivan@r4ven-me
Нажмите, чтобы развернуть и увидеть больше

На этом настройка клиента завершена, переходим к серверной части.

Подготовка на сервере - test.r4ven.me

Теперь на сервере создаём специально настроенный authorized_keys для SSH:

BASH
mkdir -p ~/.ssh/

chmod 700 ~/.ssh/

echo 'command="echo Pong",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXsCuHrzzbYmJXJqeui8j78pkYf+VbYuGeX8iK/W0EW ivan@r4ven-me' >> ~/.ssh/authorized_keys
Нажмите, чтобы развернуть и увидеть больше

Где в место ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXsCuHrzzbYmJXJqeui8j78pkYf+VbYuGeX8iK/W0EW ivan@r4ven-me укажите свой публичный ключ, который вывели в терминале на клиентской машине шагом ранее.

Строка в файле authorized_keys содержит публичный ключ SSH и специфическую команду. Суть в том, что при подключении по SSH с использованием соответствующего приватного ключа, вместо открытия интерактивной оболочки, будет выполнена только указанная команда, в данном примере - echo Pong🏓.

Также указаны дополнительные опции:

Серверную часть тоже настроили, давайте перейдём к тестам.

Тестирование работы Force command

Пытаемся подключиться к серверу с помощью нашего нового ключа:

BASH
ssh -i ~/.ssh/id_ed25519_test ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

Если попробовать выполнить произвольную команду, например ls -l :

В выводе все равно отобразитсяPong🏓.

Или пробросить SSH порт:

BASH
ssh -i ~/.ssh/id_ed25519_test -L 8888:localhost:9999 ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

Всё равно Pong🏓.

Практический пример: запуск команды с помощью sudo

Теперь давайте настроим, например запуск скрипта /opt/script.sh через утилиту sudo:

Создаём sudoers файл:

BASH
sudo visudo -f /etc/sudoers.d/90_script
Нажмите, чтобы развернуть и увидеть больше

Наполняем:

PLAINTEXT
ivan ALL=(root) NOPASSWD: /opt/script.sh
Нажмите, чтобы развернуть и увидеть больше

Теперь создадим на сервере тестовый script.sh:

BASH
echo -e '#!/usr/bin/bash\necho Sudo-Script-Pong' | sudo tee /opt/script.sh

sudo chmod 700 /opt/script.sh
Нажмите, чтобы развернуть и увидеть больше

Редактируем файл ~/.ssh/authorized_keys и меняем команду на sudo /opt/script.sh:

BASH
from="10.10.10.5",command="sudo /opt/script.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXsCuHrzzbYmJXJqeui8j78pkYf+VbYuGeX8iK/W0EW ivan@r4ven-me
Нажмите, чтобы развернуть и увидеть больше

Давайте протестируем его работу с клиента, на котором мы сгенерировали ключ: id_ed25519_test.

Пробуем подключиться к серверу:

BASH
ssh -i ~/.ssh/id_ed25519_test ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

В ответ вы должны получить Sudo-Script-Pong из нашего script.sh:

Если это так, то мы все настроили корректно. Наполните script.sh необходимой вам логикой и запускайте безопасно.

Разрешить только передачу файлов через sftp

Подобным образом можно разрешить доступ только к подсистеме передачи файлов sftp. В этом случае строка в authorized_keys будет выглядеть так:

BASH
command="internal-sftp",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXsCuHrzzbYmJXJqeui8j78pkYf+VbYuGeX8iK/W0EW ivan@r4ven-me
Нажмите, чтобы развернуть и увидеть больше

А подключаться так:

BASH
sftp -i ~/.ssh/id_ed25519_test ivan@test.r4ven.me
Нажмите, чтобы развернуть и увидеть больше

Вместо заключения

Важно понимать, что механизм forced command в SSH значительно снижает риск неправомерного использования ключа, но он не является абсолютной защитой: если ограниченная команда или сценарий содержат уязвимости (например, позволяют выполнять произвольные аргументы, подменять файлы или эскалировать доступ), злоумышленник всё равно может обойти ограничения.

Поэтому с умом подходите к настройке безопасности своих систем. Удачи!

Авторские права

Автор: Иван Чёрный

Ссылка: https://r4ven.me/networking/forced-command-v-ssh-zapusk-tolko-odnoy-komandy-bez-dostupa-k-obolochke/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша