Разрешить обычным пользователям SSH использовать закрытый ключ, который они не могут прочитать

8

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

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

Чтобы реализовать эту конфигурацию, у меня была идея использовать SSH-прокси, в который будет входить персонал службы поддержки (с аутентификацией LDAP, но это еще одна проблема), и который содержит закрытые ключи.

Вопрос в том, как разрешить персоналу службы поддержки использовать закрытый ключ SSH, не читая его?

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

Raspbeguy
источник
Отредактировал вопрос, потому что «клиентские машины» могут быть трудны для понимания (не означает противоположность сервера).
Распбегуй
Это очень много смелых, и большинство из них кажется посторонним. Это отвлекает. Как вы думаете, в будущем вы могли бы использовать гораздо меньше смелых? Спасибо.
DW
Я предполагаю , что authorized_keys ограничение относится только к динамическим изменениям (например, когда новый опорный элемент присоединяется / листы), так как вы нужны первоначальная конфигурация в машине клиента.
Анхель

Ответы:

6

Я бы предложил пару вариантов.

  1. Защитите ключ ssh и потребуйте использования команды sudoподдержки. Вы можете сделать это прозрачно с помощью обертки. Вызовите оболочку, скажем, /usr/local/bin/ssh-supportи пусть она будет содержать что-то вроде этого (не проверено):

    #!/bin/bash
    export PATH=/usr/local/bin:/usr/bin:/bin
    export IFS=$' \t\n'
    export SUSER=ssupport
    
    # Restart if not running under sudo
    test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@"
    shift
    export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)"
    
    # Extract single argument as hostname LABEL and validate that we have
    # an RSA private key for it. The target username, real hostname, port,
    # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport)
    label="$1"
    idfile="$SUSER/.ssh/id_rsa_for_$label"
    cgfile="$SUSER/.ssh/config"
    
    ok=true
    [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; }
    [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; }
    [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; }
    
    if test -n "$ok"
    then
        logger -t ssh-support "$SUDO_USER requested ssh to $label"
        exec ssh -i "$idfile" -F "$cgfile" "$label"
    fi
    exit 1

    Это потребует записи в sudoersфайле, которая позволит пользователям в supportгруппе использовать инструмент. Эта команда позволяет им запускать ssh-supportинструмент от имени ssupportпользователя, который вы должны создать. Это не дает никаких привилегий root.

    %support ALL = (ssupport) /usr/local/bin/ssh-support

    Если вы удовлетворены тем, что пользователям службы поддержки не нужно предоставлять свой собственный пароль для запуска инструмента (в соответствии с запросом, вызванным самим sudoсценарием), вы можете изменить sudoersопределение следующим образом:

    %support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support

    Предполагая, что вы PATHсодержали, /usr/local/bin/вы бы назвали это с ssh-support clientname. Также предположим, что вы создали ssupportпользователя так же, как /home/ssupportвы создали бы /home/ssupport/.ssh/id_rsa_clientnameи /home/ssupport/.ssh/id_rsa_clientname.pubкак пару сертификатов, и у вас есть запись хоста /home/ssupport/.ssh/configдля clientnameэтого, определяющая пользователя, хост, порт и т. Д. Для целевой машины. Возможно, вы явно отключите пересылку X11, переадресацию портов и т. Д. Как обычно, /home/ssupport/.sshкаталог должен быть защищен разрешениями 0700.

  2. Предоставьте каждому участнику поддержки свою собственную учетную запись локального пользователя, и пусть каждый человек использует свой собственный закрытый ключ ssh для доступа к серверам клиента. Когда человек покидает группу поддержки, вы удаляете его ключ ssh с серверов клиента. Это означает, что вам больше не нужно беспокоиться о том, чтобы ваши сотрудники не знали секретный ключ ssh.

roaima
источник
Второй вариант недействителен. Как я уже сказал, на клиентских серверах есть только одна учетная запись поддержки, и вы не можете добавлять открытые ключи в конфигурацию ssh, это правила. Фактически, вы не можете ничего изменить в конфигурации ssh на клиентских машинах.
Распбегуй
4
Кстати, этот ответ является типичным примером использования (ab) sudo. Я написал статью на эту тему ( dmitry.khlebnikov.net/2015/07/… ), похоже, что существует тенденция пытаться что-то решить с помощью sudo. Однако это только ослабляет безопасность ваших систем и не улучшает ее.
галактика
1
@Raspbeguy, конечно, они не будут. sudoersПределы линии доступа к одной команде
roaima
1
Вы передаете непроверенные параметры в ssh с помощью $ @, который запускается от имени пользователя root! Я могу подумать о разных способах испортить системные системные файлы (использовать -Eдля добавления), переадресовать привилегированные порты ( -L,-R,-D) или просто получить root ( -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'комментарий от galaxy о злоупотреблении sudo
тут же
1
@roaima: Так или иначе, у вашей идеи sudo to root есть проблемы, но они отличаются от тех, о которых говорилось в блоге galaxy. Он говорит о ssh root@somewhereключах, ssh user@somewhereа не о Судо. Это действительно хороший момент. Тем не менее, единственный способ, которым это применимо к этому делу, ssh keyowner@localhost ssh_to_client client.example.org - это альтернатива sudo -u keyowner ssh_to_client client.example.org. Подобно sudo, SSH может ограничивать команды, которые пользователю разрешено запускать. Мы говорим о sudo без пароля для пользователя root, а не в случае использования Galaxy.
Питер Кордес
11

Что вы действительно хотите сделать, так это использовать SSH CA и подписывать ключи, используемые каждым специалистом службы поддержки (у них должны быть свои собственные ssh-ключи, например, паспорта), и настраивать серверы ваших клиентов для использования TrustedUserCAKeys /etc/ssh/users_ca.pubв / etc / ssh / sshd_config. Таким образом, сервер примет любой ключ, подписанный ключом CA (к которому у вас есть доступ), и вы сможете отозвать ключи людей, которые больше не поддерживают, даже не касаясь авторизованных ключей.

Быстрый поиск «ssh ca» указал на этот учебник: https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with -ubuntu (прокрутите вниз до раздела «Как настроить пользовательские ключи») - хотя в руководстве упоминается Ubuntu, он не зависит от распространения, но вам нужна свежая версия OpenSSH, которая поддерживает SSH CA

Еще одна хорошая запись в блоге на эту тему - https://ef.gy/hardening-ssh (прокрутите вниз до «Сертификаты SSH»).

Обратите особое внимание на то, что вы можете подписать ключ, чтобы он действовал в течение ограниченного времени, чтобы он автоматически истек!

галактика
источник
Было бы неплохо, если бы компьютеры клиентов имели доступ к Интернету (чтобы обновить действительность подписи), что не всегда так. Мы подключаемся к этим машинам через VPN, предоставленную клиентом.
Распбегуй
Ну, это настолько близко, насколько это возможно, не передавая ключ человеку, который покидает вашу компанию. Я предоставил вам механизм, вы можете его автоматизировать, например, у вас может быть дежурный сотрудник, который будет поддерживать ваш отдел кадров, когда люди уходят из компании, и вы можете определить процедуру отзыва ключей.
галактика
1
Кроме того, вы можете подписать ключ (один из сотрудников службы поддержки) в течение ограниченного времени - например, вы можете подписать его только на 8 часов (для их смены), через 8 часов он истечет, и сервер их не пропустит.
galaxy
3
Что касается вашей части LDAP - в настоящее время я работаю в компании, которая управляет сотнями экземпляров, и мы работаем над решением с открытым исходным кодом для интеграции SAML 2.0 и SSH CA. Идея состоит в том, что человек аутентифицируется с помощью единого входа и, если он авторизован, подписывает свои ключи в течение определенного периода времени (например, 5 минут). Все это довольно прозрачно для пользователя и реализовано с помощью ~ / .ssh / config ProxyCommand.
галактика
2

Существует несколько различных ответов, включающих скрипт-обертку для ssh, вызываемый через sudo или setuid-исполняемый файл (для какой-то специальной учетной записи без полномочий root ). Как говорит nkms , прохождение всех аргументов через ssh позволяет пользователю выполнять произвольные действия с ключами ssh, которые мы пытаемся защитить. Другая крайность, которую некоторые придумали, - разрешить только имя хоста.

ОП говорит, что администраторы должны иметь возможность загружать вещи.

У вас может быть две разные оболочки fixed-args-to-ssh. Один для входа в систему, другой для scp. Нет пользовательских аргументов, кроме имени хоста (и имени файла для загрузки).

Или скрипт-обертка, который использует getoptсам себя для разбора очень ограниченных опций и включения вещей в в основном фиксированную команду ssh. Игнорирование (или ошибка) для нераспознанных опций - это путь.

Не пытайтесь отфильтровать «опасные» параметры ssh, просто напишите обертку, которая может делать две вещи: интерактивный вход в систему или загрузку файла (локальные и удаленные имена файлов). Я думаю, тебе все еще нужно провести там дезинфекцию.

На самом деле, все еще легко ошибиться. Вы должны найти способ запретить пользователю давать файл, содержащий ключи ssh, как локальный файл. Таким образом, вы все еще пытаетесь думать обо всем, что нужно запретить, вместо того, чтобы начинать с того, чтобы ничего не позволять. Было бы неплохо убедиться, что имена файлов не содержат ни одного, @ни :.

Питер Кордес
источник
Идея обертки действительно является решением, но это подразумевает брешь в безопасности, которую необходимо устранить.
Raspbeguy
Я поражен тем, как люди заново изобретают колесо, когда в этом нет необходимости. Функциональность SSH CA была введена в OpenSSH именно по причинам и ситуации, подобным первоначальному вопросу. Мое решение не использовало никаких оболочек и получало именно то, о чем просили, но по какой-то причине @Raspbeguy решила пойти своим путем с сомнительными последствиями для безопасности. :)
галактика
@galaxy: да, ваше решение SSH CA наверняка будет лучшим, если только у вас нет абсолютного требования, что вы не можете внести одноразовые изменения в удаленные системы, чтобы сконфигурировать их sshd для его использования. Это звучит идеально, и легко получить право.
Питер Кордес
@galaxy: ваше решение действительно элегантно, но не применимо в моем случае, как я говорил вам ранее. Мне очень нравится идея, я говорил об этом своему боссу, но это все еще невозможно. Не нужно расстраиваться.
Распбегуй
1
@Raspbeguy, я не расстроен, я просто не понимаю, почему ваша компания хочет пожертвовать своей безопасностью и внедрить что-то, используя «клейкую ленту», когда есть правильный способ сделать это. И ваш комментарий состоял в том, что это было бы хорошим решением, но вам не понравилось, что вы не можете автоматизировать отзыв - и я также предоставил вам решение для этого (подписав ключи только для смены). В любом случае, вы выбрали свой ответ, давайте двигаться дальше :)
галактика
1

Если вы настроили прокси-сервер SSH, вы можете договориться, что оболочка (in /etc/passwd) ваших сотрудников не настроена на оболочку, такую ​​как bash, а вместо этого представляет собой простой скрипт, который не разрешает доступ к оболочке. Вместо этого он запросил бы целевое имя хоста ( read target), затем exec ssh "support@$target".

Обратите внимание, что использование такого прокси-сервера может затруднить использование таких инструментов, как scpпередача файлов на клиентские компьютеры или с них. Это может быть проблемой или преимуществом!

Тоби Спейт
источник
Эта идея-скрипт-обертка похожа на идею @ roaima. Вы даете доступ к нему с помощью SSH, но sudoтакже работает. В его ответе предлагается использовать локального пользователя root, но не пользователь root тоже подойдет. Смотрите мои комментарии на его ответ для обсуждения этого. (Моя ssh keyowner@localhostидея совпадает с вашей идеей.)
Питер Кордес
@Peter - совершенно верно: root совершенно не подходит для этого!
Тоби Спейт
Поддерживает, ребята должны загружать вещи, поэтому это решение может не работать.
Raspbeguy
@Raspbeguy: опубликовал ответ на этот вопрос. Используйте в сочетании с установкой без прав root sudo.
Питер Кордес
0

Сотрудники службы поддержки всегда подключаются через этот прокси-сервер и только с него, поэтому клиенты могут просто аутентифицировать прокси-компьютер с помощью HostbasedAuthentication .

Допустим, прокси-машина supporters.pcи вы оказываете поддержкуcustomer.pc

customer.pc будет HostbasedAuthentication да в /etc/ssh/ssd_config, supporters.pc перечисленных в /etc/ssh/shosts.equivи его открытый ключ /etc/ssh/ssh_known_hosts.

Когда ваш персонал службы поддержки ssh customer.pcвойдет в support@supporters.pc и выполнит его, он вызовет ssh-keysign (8) (который должен быть настроен), который будет обрабатывать подпись ключей с помощью файла, который вы не можете прочитать, и предоставить доказательство supporters.pc, что соединение действительно происходит с supporters.pc . Поскольку customer.pc доверяет supporters.pc , ваш сотрудник входит в систему поддержки .

Анхель
источник
Это ужасное решение с точки зрения безопасности, поскольку, если вы предоставляете доступ к машине в целом и теряете ответственность за то, кто что сделал. Доверие между компьютерами должно быть запрещено в современном мире, где ИТ-безопасность начала становиться довольно горячей темой.
галактика
@ galaxy, из OP я понимаю, что они уже делают это в основном. Доверие к этой машине находится в спецификации . Обратите особое внимание на то, что они «используют только одну учетную запись на машине (учетная запись для доступа в службу поддержки)», возможно, они используют общую учетную запись в customer.pc, но подключаются к серверу в качестве своего собственного пользователя. Изменение разрешений ssh ​​и ssh-keygen для принудительной поддержки sudo -u ssh… решит эту проблему, а также добавит запись в журнал.
Анхель
0

Используйте бинарный файл-обертку

Для этого конкретного случая использования (см. Важное примечание ниже), одна возможность состоит в том, чтобы создать пользователя (скажем support-ssh) специально для этих исходящих соединений SSH, а затем установить небольшой двоичный файл-обертку, который исполняется /usr/bin/ssh.

  • Не копируйте + chmod сам sshбинарный файл, потому что вы не забудете повторять его каждый раз, когда применяете обновления безопасности.
  • И не используйте rootв качестве более привилегированного пользователя, по причинам, которым я доверяю, это очевидно.

Это функционально эквивалентная альтернатива использованию sudoдля повышения привилегий support-sshучетной записи со следующими компромиссами:

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

Двоичный файл оболочки должен указывать HOMEна support-sshдомашний каталог пользователя, чтобы sshподобрать соответствующий ssh_configи закрытый ключ. Но вызывающему пользователю не должно быть разрешено читать ~support-ssh/.ssh/или его содержимое.

Обертка может быть такой простой, как:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    setenv("HOME", "/home/support-ssh", 1);
    /* allow only a single, non-option argument */
    if (argc!=2 || *argv[1]=='-') {
        fprintf(stderr, "Usage: %s <hostname>", argv[0]);
        exit(EXIT_FAILURE);
    }
    execv("/usr/bin/ssh", argv);
    return EXIT_FAILURE;
}

Вы можете захотеть быть более строгим и проверить, что аргумент argv[1]находится в наборе разрешенных имен хостов. Или менее строгие, и позволяют (подмножество) аргументов опции. Возможно, вы захотите полностью заменить переменные окружения (но оставьте важные, такие как TERM, LC_*и т. Д.); обратите внимание, что LD_LIBRARY_PATHи LD_PRELOADособенно опасно.

Аналогичная программа-обертка может быть предоставлена ​​для scpпри необходимости.

Примечание о применимости

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

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

Тоби Спейт
источник
Вы передаете непроверенные аргументы ssh, работающему от имени другого пользователя, см. Мой комментарий к ответу выше. Я все еще могу прочитать ключ ... и я бы не стал рассчитывать на строгую проверку аргументов, ssh не предназначен для этого.
nkms
@nkms - я сделал оболочку более строгой. При необходимости его можно сделать более открытым, но вы вправе заблокировать все, кроме случаев, когда требуется, а не наоборот.
Тоби Спейт
@TobySpeight: да, выглядит хорошо. В любом случае я положил большую часть того, что сказал в комментариях, в свой ответ
Питер Кордес
1
Было бы лучше использовать sudo, чем двоичную оболочку. Вопреки тому, что вы утверждаете, использование sudo намного менее рискованно, чем использование собственного. Судо имеет безопасные значения по умолчанию. Вы уверены, что не забыли удалить переменную окружения, которая будет влиять на ssh?
Жиль "ТАК - перестать быть злым"