通常のユーザーが読み取りできない秘密鍵を使用してSSHで接続できるようにする


8

少数のユーザー(サポートスタッフと呼ばれる)だけがSSHにアクセスできるマシンのセット(ここでは顧客のマシンと呼ばれます)があり、マシンごとに1つのアカウント(サポートアクセスアカウント)のみを使用するとします。

サポートスタッフは、キーを使用して顧客のマシンにログインすることのみが想定されています。さらに、サポートスタッフは進化する可能性があるため、サポートスタッフを離れた人は、お客様のマシンにログインすることはできません。そのため、スタッフはお客様のマシンへのログインに使用される秘密鍵を読み取ることを禁止されています。また、authorized_keysお客様のマシン上でファイルを改変することは禁じられています。

この構成を実現するために、私はサポートスタッフが(LDAP認証を使用してログインしますが、これは別の問題です)秘密鍵を含むSSHプロキシを使用するという考えを持っていました。

問題は、サポートスタッフがSSH秘密キーを読み取ることなく使用できるようにするにはどうすればよいですか。

ユーザーの要求を受け入れ、それらのSSHセッションを開くプロキシマシンでrootとして実行するデーモンを作成する必要があると思いますが、それを行う方法がわかりません。何か案は?


「クライアントマシン」は理解しにくいため、質問を編集しました(サーバーの反対を意味するものではありません)。
Raspbeguy、2015

それは非常に大胆で、ほとんどが無関係なようです。気が散ります。将来、大胆さを大幅に減らすことができると思いますか?ありがとうございました。
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
    

    これにはsudoerssupportグループ内のユーザーがツールを使用できるようにするファイル内のエントリが必要です。このコマンドを使用するとssh-supportssupportユーザーはツールをユーザーとして実行できます-ユーザーが作成する必要があります。ルート権限付与されません

    %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キーを知るのを防ぐことについて心配する必要がなくなったことを意味します。


2番目のオプションは無効です。先ほど述べたように、クライアントサーバーにはサポートアカウントが1つしかなく、公開鍵をssh構成に追加することはできません。それがルールです。実際、クライアントマシンのssh設定については何も変更できません。
Raspbeguy、2015

4
ちなみに、この答えはsudoを使用する(ab)の典型的な例です。私はそのトピックに関する記事を書きました(dmitry.khlebnikov.net/2015/07/…)、sudoを使用して何でも解決しようとする傾向があるようです。ただし、これはシステムのセキュリティを弱めるだけで、改善はしません。
銀河

1
@Raspbeguyもちろんそうしません。このsudoers行は、単一のコマンドへのアクセスを制限します
roaima

1
ルートとして実行される「$ @」を使用して、チェックされていないオプションをsshに渡します。私はエーテル壊れたシステムファイルに異なる方法(使用を考えることができます-E追加する)、前方特権ポート(-L,-R,-D)または単にゲインルート(-o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'sudoを乱用についての銀河からのコメントは正しい場所にあります。!
nkms

1
@roaima:とにかく、sudo to rootのアイデアには問題がありますが、それらはgalaxyのブログ投稿で話されたものとは異なる問題です。彼ssh root@somewhereはキーで話しているのではなくssh user@somewhere、sudoで話している。それは実際には本当に良い点です。ただし、このケースに適用できる唯一の方法ssh keyowner@localhost ssh_to_client client.example.org は、の代替方法 sudo -u keyowner ssh_to_client client.example.orgです。sudoと同様に、SSHはユーザーが実行を許可されるコマンドを制限できます。Galaxyのユースケースではなく、非rootに対するパスワードなしのsudoについて話しています。
Peter Cordes

11

本当にやりたいことは、各サポート担当者が使用するSSH CAと署名キー(パスポートのような独自のsshキーが必要)を使用TrustedUserCAKeys /etc/ssh/users_ca.pubし、/ etc / ssh / sshd_configでを使用するようにクライアントのサーバーを構成することです。このようにして、サーバーはCAキー(アクセス権を持つ)によって署名されたすべてのキーを受け入れ、authorized_keysに触れることなくサポートされなくなった人々のキーを取り消すことができます。

このチュートリアルを指す「ssh ca」のクイック検索:https : //www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with -ubuntu(「ユーザーキーの設定方法」までスクロールします)-チュートリアルではUbuntuについて言及していますが、ディストリビューションには依存しませんが、SSH CAをサポートする新しいバージョンのOpenSSHが必要です

このトピックに関するもう1つの優れたブログエントリは、https://ef.gy/hardening-sshです(「SSH証明書」までスクロールします)。

キーに署名して一定期間有効にすることで、キーが自動的に期限切れになることに特に注意してください。


顧客のマシンがインターネットにアクセスできる場合(署名の有効性を更新する場合)は良い考えですが、常にそうであるとは限りません。お客様から提供されたVPNを介してこれらのマシンに接続します。
Raspbeguy、2015

さて、これはあなたが会社を去る人と鍵を漏らさずに得ることができる限り近いです。私はメカニズムを提供しました。それを自動化できます。たとえば、人が会社を辞めたときに人事担当者をサポートし、鍵を取り消す手順を定義できます。
銀河

1
また、あなたは限られた時間のためのキー(サポート担当者の1)に署名することができます-あなたは(自分のシフトのために)わずか8時間のためにそれに署名することができ例えば、8時間後にそれが失効すると、サーバは、それらの中にさせません。
銀河を

3
LDAPの部分について-私は現在、数百のインスタンスを管理している会社で働いており、SAML 2.0とSSH CAを統合するためのオープンソースソリューションに取り組んでいます。個人がSSOを使用して認証し、承認された場合、定義された期間(たとえば、5分間)署名されたキーを取得するという考え方です。これはすべてユーザーに対して透過的であり、〜/ .ssh / configのProxyCommandを使用して実装されます。
銀河

2

sudoまたはsetuid-executable(特定の非rootアカウントに対して)を介して呼び出されるsshのラッパースクリプトに関するいくつかの異なる回答があります。以下のようnkmsは言う、SSHにすべての引数を通過すると、ユーザーは、我々が保護しようとしているSSHキーで任意のものを行うことができます。一部のユーザーが考え出したもう1つの極端な例は、ホスト名のみを許可することです。

OPは、管理者がアップロードできる必要があると述べています。

2つの異なるfixed-args-to-sshラッパーを使用できます。1つはログインシェル用、もう1つはscp用です。ホスト名(およびアップロードするファイル名)以外のユーザー指定の引数はありません。

または、getoptそれ自体を使用して非常に限られたオプションを解析し、ほとんどが修正されたsshコマンドにプラグインするラッパースクリプト。認識されないオプションを無視(またはエラー)するのがよいでしょう。

「危険な」sshオプションを除外するのではなく、対話型ログイン、またはファイルのアップロード(ローカルおよびリモートのファイル名)の2つのことを実行できるラッパーを作成するだけです。あなたはまだそこにいくつかの消毒をする必要があると思います。

実際、これはまだ間違いやすいです。ユーザーがsshキーを保持するファイルをローカルファイルとして提供できないようにする方法を見つける必要があります。したがって、何も許可しないことから始めるのではなく、許可する必要のあるすべてのものを考えようとしています。ファイル名に@or が含まれていないことを確認することから始めます:


確かにラッパーのアイデアが解決策ですが、これは、満たさなければならないセキュリティ違反を意味します。
Raspbeguy

ホイールが必要なくなったときに、人々がホイールを再発明していることに驚いています。SSH CA機能は、元の質問のような理由と状況のためにOpenSSHに導入されました。私のソリューションはラッパーを使用せず、要求されたものを正確に達成しましたが、何らかの理由で、@ Raspbeguyは疑わしいセキュリティ上の影響を伴うDIYの方法を採用することにしました。:)
銀河

@galaxy:ええ、SSH CAソリューションは確かに最良のものです。ただし、リモートシステムに一度だけ変更を加えて、それを使用するようにsshdを構成することができないという絶対的な要件がない限りです。それは完璧に聞こえ、正しく理解するのは簡単です。
Peter Cordes

@galaxy:あなたのソリューションは本当にエレガントですが、先ほどお話ししたように、私の場合には適用できません。私は本当にそのアイデアが好きで、上司にそれについて話しましたが、それはまだ不可能です。動揺する必要はありません。
Raspbeguy、2015

1
@Raspbeguy、私は動揺していません、あなたの会社がセキュリティを犠牲にして、適切な方法があるときに「ダクトテープ」を使用して何かを実装したい理由を理解していません。そして、あなたのコメントはそれが良い解決策になるだろうということでしたが、あなたは失効を自動化できなかったのが嫌でした-そして私はこれに対する解決策もあなたに提供しました(シフトのキーのみに署名することによって)。とにかく、あなたはあなたの答えを選択し、先に進みましょう:)
銀河

1

SSHプロキシサーバーを設定すると、スタッフユーザーのシェル(内/etc/passwd)がbashなどのシェルではなく、シェルアクセスを許可しない単純なスクリプトに設定されるようにすることができます。代わりに、ターゲットのホスト名(read target)、次にを要求しexec ssh "support@$target"ます。

このようなプロキシを使用するとscp、顧客のマシンとの間でファイルを転送するなどのツールを使用することが困難になる可能性があることに注意してください。これは問題かもしれませんし、利点かもしれません!


これはラッパースクリプトのアイデアであり、@ roaimaのアイデアに似ています。あなたはsshでそれにアクセスを与えていますが、sudoうまくいきます。彼の答えはローカルのrootユーザーを使用することを提案していますが、非rootユーザーも機能します。それについての議論のために彼の答えに関する私のコメントを見てください。(私のssh keyowner@localhost考えはあなたの考えと同じです。)
Peter Cordes

@ピーター-完全に正しい:rootは絶対に間違ったユーザーです!
Toby Speight

サポート担当者がアップロードする必要があるため、このソリューションは機能しない可能性があります。
Raspbeguy、2015

@Raspbeguy:これに対処する回答を投稿しました。roaimaの非root sudoセットアップと組み合わせて使用​​します。
Peter Cordes

0

サポート担当者は常にそのプロキシマシンを介して接続し、そのプロキシマシンからのみ接続するため、クライアントはHostbasedAuthenticationを使用してプロキシマシンを簡単に認証できます。

プロキシマシンがsupporters.pcあり、サポートを提供するとしますcustomer.pc

customer.pcにはHostbasedAuthentication yesがあり/etc/ssh/ssd_configsupporters.pcにリストされ/etc/ssh/shosts.equiv、その公開鍵にはがあり/etc/ssh/ssh_known_hostsます。

サポートスタッフがsupport@supporters.pcにログインしてを実行するとssh customer.pcssh-keysign(8)(これはsetuidである必要がありますを生成します。接続がsupporters.pcから実際に行われているという証拠をsupporters.pcに提供ます。以下のようcustomer.pc信託supporters.pc、あなたのスタッフがなどに記録されますサポート


マシン全体へのアクセスを許可すると、誰が何をしたかについての説明責任が失われるため、これはセキュリティの観点からすごい解決策です。マシン間の信頼は、ITセキュリティが非常にホットなトピックとして浮上し始めた現代の世界から禁止されるべきです。
銀河

@ galaxy、OPから私の理解は、彼らは基本的にそれをすでに行っているということです。そのマシンへの信頼は仕様にあります。特に、「マシンごとに1つのアカウント(サポートアクセスアカウント)のみを使用している」ことに注意してください。customer.pcの共有アカウントを使用している可能性がありますが、サーバーに自分のユーザーとして接続します。sudoおよびssh-keygenの権限を変更して、sudo -uサポートssh…を強制することでそれを解決し、ログエントリも追加します。
アンヘル・

0

ラッパーバイナリを使用する

この特定の使用例(以下の重要な注意を参照)の場合、1つの可能性はsupport-ssh、これらの発信SSH接続専用のユーザーを(たとえば)作成し、実行する小さなラッパーバイナリをインストールすること/usr/bin/sshです。

  • sshセキュリティアップデートを適用するたびにバイナリを再コピーすることを覚えていないため、バイナリ自体をコピー+ chmodしないでください。
  • そしてroot、私が信頼している理由が明白であるため、より特権的なユーザーとして使用しないでください。

これは、次のトレードオフを使用sudoして、特権をsupport-sshアカウントの特権に昇格するのに使用する機能的に同等の代替手段です。

  • これはよりも小さくてスリムなのでsudo、意図したよりも多くの構成エラーが開くリスクが少なくなります。
  • 正しくコーディングするのはあなたの責任です- 非常に注意深く、(理想的には)セキュリティ上重要なコーディングの経験がある場合にのみ、これを行ってください。
  • これは、より具体的になるように調整できますsudo(ただし、作成するコードが増えるほど、セキュリティのために監査する必要が増えます)。

ラッパーバイナリはHOMEsupport-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]が許可されたホスト名のセットに含まれていることを確認してください。または、制限が少なく、オプションの引数(のサブセット)を許可します。あなたは完全に環境変数を置き換えることもできます(ただし、のような重要なものを維持するTERMLC_*など)。それを注意LD_LIBRARY_PATHし、LD_PRELOAD特に危険です。

scp必要に応じて、同様のラッパープログラムを提供できます。

適用性に関する注意

この回答は、ユーザーが契約に従って手続きに従う義務があり、違反した場合の制裁措置(解雇など)がある質問の特定の状況に対処します。攻撃者が不正なアクセスを取得するのを防ぐのではなく、従業員が秘密鍵を何気なくコピーするのを防ぎたいと想定しています。

私は、セキュリティは技術的な防御と非技術的な防御の両方によって達成され、ここでまたは使用することによって達成されるバランスsudoは、提示された状況に適切であると考えています。


チェックされていない引数を別のユーザーとして実行しているsshに渡します。上記の回答に関する私のコメントを参照してください。私はまだ鍵を読むことができます...そして私は厳密な引数チェックを当てにしません、sshはそのような方法で実行することを意図していません。
nkms

@nkms-ラッパーをより制限的にしました。必要に応じて、よりオープンにすることができますが、逆の場合よりも、必要な場合を除いて、ロックする権利があります。
Toby Speight

@TobySpeight:うん、よさそうだ。とにかくコメントで言ったことのほとんどを自分の答えに入れました。
Peter Cordes

1
バイナリラッパーよりもsudoを使用する方が良いでしょう。あなたが主張することに反して、sudoを使用することは、自分でロールするよりもはるかにリスクが少ないです。Sudoには安全なデフォルトがあります。sshに影響を与える環境変数を削除することを忘れていないことをどれだけ確信していますか?
Gilles「SO-邪悪になるのをやめる」
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.