ログイン後にSSHユーザーを事前定義されたコマンドのセットに制限するにはどうすればよいですか?


85

これはセキュリティのアイデアです。当社の従業員は、Linuxサーバー上の一部のコマンドにアクセスできますが、すべてではありません。たとえば、ログファイルにアクセスしless logfileたり()、別のコマンドを開始したりする可能性があります(shutdown.sh/ run.sh)。

背景情報:

すべての従業員が同じユーザー名でサーバーにアクセスします。当社の製品は「通常の」ユーザー権限で実行され、「インストール」は必要ありません。ユーザーディレクトリで解凍して実行するだけです。アプリケーションが「インストール」されている複数のサーバーを管理しています。すべてのマシンにユーザーがいますjohndoe。当社の従業員は、ログファイルにアクセスして確認したり、アプリケーションを手動で再起動したりするために、コマンドラインでアプリケーションにアクセスする必要がある場合があります。一部の人だけが完全なコマンドラインアクセスを持っています。

サーバーでppk認証を使用しています。

employee1がログファイルにのみアクセスでき、employee2もXなどを実行できると便利です。

解決策:解決策 としてcommand受け入れられた回答に記載されているオプションを使用します。一部の従業員が実行できる唯一のファイルとなる独自の小さなシェルスクリプトを作成します。スクリプトは実行可能ないくつかのコマンドを提供しますが、他のコマンドは提供しません。ここにauthorized_keys記載されているように、fromで次のパラメーターを使用します。

command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host

これは私たちにとって十分なセキュリティです。ありがとう、コミュニティ!


標準のLinuxACL権限ベースのセキュリティでは不十分ですか?どのような追加機能が必要ですか?
ジェイムズ・ブレイディ

22
それはひどい考えです、マルセル。
Vinko Vrsalovic 2008

13
@ Vinko、@ PEZ:いくつかの背景情報を追加しました。「愚かな考え」と言う代わりに、価値のあるコメントを提供することができます。あなたの意見では、より良いアイデアは何ですか?
マルセル

8
複数のユーザーが同じユーザー名を共有することについて、まだ言い訳はありません。
Eldelshell 2008

3
「私自身の小さなシェルスクリプト」?かなり危険に聞こえます。あなたが専門家でない限り、それから完全なシェルに逃れる方法はおそらくたくさんあります。私はむしろ、よく書かれ、デバッグされ、維持されているプログラムを信頼したいと思います(いくつか言及されています)。
bortzmeyer 2009年

回答:


68

キーを許可されるコマンド(authorized_keysファイル内)に制限することもできます。

つまり、ユーザーはssh経由でログインせず、制限されたコマンドセットを使用しますが、ssh経由でのみこれらのコマンドの実行を許可されます(例: "ssh somehost bin / showlogfile")


面白そうですね。複数のコマンドを定義することは可能ですか?
マルセル

12
この記事では、authorized_keysファイルを使用した複数のコマンドのオプションをいくつか紹介します。linuxjournal.com
Bash

@ rd834 ...:どうもありがとう。これは私に「良い」解決策を与えたと思います...(質問に追加されました)。私はこの答えを「正しい」と認めます。
マルセル

11
O'Reilly SSHの本には、SSH_ORIGINAL_COMMAND環境変数を調べるスクリプトを設定して複数のコマンドを許可するなど、これを行う方法についての優れた説明があります。 oreilly.com/catalog/sshtdg/chapter/ch08.html
Alex Dupuy

5
このserverfaultの回答には、エクスポートされたSSH_ORIGINAL_COMMAND変数を使用して複数のコマンドを許可する方法に関する優れたヒントがあります。
MattBianco 2015年

32

sshrshパスワードファイルからユーザーのシェルプログラムを使用してコマンドを実行することにより、伝統に従います。

これは、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コマンド全体を1つの引数として、それ/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か?
イエティ2017

@Yetiここにコマンドインジェクションホールはありますか?これに対処する必要があります。また、私が行ったファイルパターンの乱用は、私にはcase正しく見えません。
kaz

1
はい、/bin/bash -c "$2"安全ではありません(SQLインジェクションの動作と同様)。PHPのような「魔法の引用符」で文字列をフィルタリングできます。ただし、セキュリティを完全に確保する簡単な方法は、コマンドを手動で呼び出してから、パラメータを二重引用符で囲むことです。全体のセキュリティは、そのコマンドが最も弱いリンクであることに依存しているためです(検証が困難です)。あなたの答えが22の賛成票を持っているのを見るのが最も興味深いですが、誰もこれに気づいていません;)あなたはあなた自身の答えを更新しますか?
イエティ

1
@Yetiはい; 今やりました。スクリプトを、-c引数をで中断しset、最初の2つの単語のみを取得するスクリプトに置き換えました。1つ目は許可されたgit-コマンドである必要があり、2つ目は正規化され、許可されたプレフィックスと照合され、存在も確認されるパスである必要があります。これを打破する方法を考えられますか?
kaz 2017

1
誰かが指定されたコマンドのいずれかのエイリアスを作成(またはコマンドをオーバーライド)しない限り、いいえ、Bashの二重引用符は安全であるはずです(そうでない場合、これはBashのバグです)。
イエティ2017

15

あなたが探しているものは制限付きシェルと呼ばれています。Bashは、ユーザーがホームディレクトリにあるコマンドのみを実行できる(そして他のディレクトリに移動できない)モードを提供します。これで十分かもしれません。

少し古くなっていれば、このスレッドは非常にわかりやすいものであることがわかりました。


1
ユーザーが「!/ bin / sh」などのプロンプトを表示しない場合はどうなりますか?
PEZ

3
@Ubersoldat:成長して、すべての投稿で攻撃性を抑えてください。彼は、制限がbashまたは子プロセスにのみ適用されるかどうかを尋ねていました(そして彼の質問に答えると、そうではないことがわかりました)。

制限付きシェルの主な問題は、シェルを保護するには、.profileまたは.bashrcを使用してPATHを制限したり、ビルトインを無効にしたりする必要があることですが、これらのファイルはインタラクティブシェルに対してのみ呼び出されます。ユーザーがsshを使用してリモートコマンドを実行した場合、それらは呼び出されません。これにより、SHELL = / bin / rbashのアカウントへのsshアクセス権を持つユーザーは、「ssh remotehost bash」のようなことを実行して、非対話型で制限のないシェルを取得できます。HDが提案するようにSSH強制コマンドが必要ですが、これはPEZが尋ねたようにシェルエスケープから保護することができます(PATHがロックダウンされると-デフォルトで/ bin:/ usr / binが含まれます)。
Alex Dupuy 2011

2
私はそれを取り戻します。sshdの下で非対話的に実行すると、bash.bashrc(.profileではなく)呼び出します。ただし、PATHを明示的に設定し、.bashrcのビルトインとエイリアスを無効にする必要があります。PATH内/上以外のサブディレクトリ、.ssh /または.bashrcに変更することもお勧めします。任意のファイルに書き込むことができるコマンドがあると、問題が発生します。これらは必ずしも明白ではありません。たとえば、sed'w 'コマンドを使用して.bashrcを上書きしてブレークアウトすることができます。chroot jailは、使用できる場合は常に安全であり、ssh強制コマンドはより制限されます。
Alex Dupuy 2011

4

制限されたシェルである `rssh 'を取得する必要があります

上記の制限ガイドに従うことができます。それらはすべてかなり自明であり、従うのは簡単です。「chrootjail」という用語、およびsshd /端末構成を効果的に実装する方法などを理解します。

ほとんどのユーザーはsshdを介して端末にアクセスするため、SSHを介して特定の制限を適用するには、SSHデーモン構成ファイルであるsshd_conifgも調べる必要があります。ただし、注意してください。誤った構成の影響はおそらくかなり悲惨なので、実装しようとしていることを正しく理解してください。


1
pizzashack.org/rsshは、scp / sftp / rdist / rsync / cvsを許可したい(そしてchroot jailの外部にアクセスする必要がない)特別な場合に最適な(おそらく最良の)ソリューションであることに注意してください-ただし、ユーザーがログファイルを表示して特定の実行/シャットダウンスクリプトを実行できるようにすることを望んでいた元の投稿者の一般的な質問は解決されません。
Alex Dupuy 2011

2
rsshDebianバスターから削除されました。新しい辛さはGNUラッシュだと思います。
トーマス

1
私は信じて@Thomas rsshには現在メンテナンスされていないで、既知のセキュリティ上の問題があります。sourceforge.net/p/rssh/mailman/message/36519118
マックスBarraclough

4

独自のログインシェルを書いてみませんか?これにBashを使用するのは非常に簡単ですが、任意の言語を使用できます。

Bashの例

お気に入りのエディターを使用してファイルを作成します/root/rbash.sh(これは任意の名前またはパスにすることができますがchown root:root、andである必要があります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

注意してください。コマンド全体と一致していることを確認し、ワイルドカードに注意してください。ベターのようなバッシュ・シンボルを除外し;&&&||$、およびバッククォートは確かに。

ユーザーに与える自由にもよりますが、これほど安全になることはありません。多くの場合、関連するいくつかのコマンドにしかアクセスできないユーザーを作成するだけでよいことがわかりました。その場合、これが本当に優れたソリューションです。しかし、あなたはより多くの自由を与えたいですか、刑務所と許可はより適切かもしれません。間違いは簡単に起こり、すでに手遅れになったときにのみ気づきます。


私はこのアプローチが本当に好きでした。「servicehttpdrestart」のようなマルチワードコマンドをどのように処理できるか考えていますか?
ファーザン2018年

2
あなたは、例えば、変数にコマンドを実行することができ@Farzanln="service httpd restart"で、: ${ln[@]}。それでもセキュリティの問題については必ず考えてください。そのような場合は、英数字と空白のみのホワイトリストが役立ちます。ただし、次のことをif [[ "$ln" == "restart-httpd"];then service httpd restart;fi実行して、そのような単純なコマンドを操作することもできます。
イエティ

/root/rbash.sh: Permission denied chmod 777も試しました
クリスチャン

@クリスチャン、追加/root/rbash.shしました/etc/shellsか?分布によって異なります。を一時的に無効にしてselinux、のファイル内の手がかりがないかログメッセージを確認する(タイムスタンプを確認する)こともできます/var/log
イエティ

@yetiいいえ、/ rootに追加するように説明されました:)今すぐ試してみます。
クリスチャン


1

GNU Rushは、これを達成するための最も柔軟で安全な方法かもしれません。

GNU Rushは制限付きユーザーシェルであり、svnまたはgitリポジトリ、scpなどのリソースへの制限付きリモートアクセスを提供するサイト向けに設計されています。GNU Rushは、高度な構成ファイルを使用して、ユーザーが実行するコマンドライン、および仮想メモリやCPU時間などのシステムリソースの使用を完全に制御できます。


0

これを見る別の方法は、POSIX ACLを使用することです。これは、ファイルシステムでサポートされている必要がありますが、Windowsで同じコントロールを使用するのと同じ方法で、Linuxですべてのコマンドをきめ細かく調整できます(UIが改善されていない場合)。 )。リンク

調べるべきもう一つのことは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コマンドのホワイトリストコントロールのようなものです。

また、さまざまなユーザーに許可されるさまざまなコマンドをサポートします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.