ルート対応スクリプトに変数を安全に渡す方法は?


13

この質問は完全に一般的なものであり、私の状況にのみ適用されるわけではありません。たとえば、DHCPを有効にする次の小さなスクリプトのよう$1に、コマンドライン(!!)で送信する変数()は、送信するホスト名のみです。

#!/bin/bash
udhcpc -b -i eth0 -h $1

このようにudhcpcを実行するにはルートアクセスが必要なので、これを行う/etc/sudoersには、次の行を含むように変更する予定です。

joe ALL = NOPASSWD: /path/to/enable_dhcp.sh

次のコマンドを実行するだけで、「joe」がそのスクリプトをルート権限で簡単に実行できるようになります

sudo /path/to/enable_dhcp.sh

パスワードを求められない(これは、joeがこれをスクリプト化できるようにするためです)。

今..私は、ルート権限で簡単に実行できるスクリプトで使用することは、あなたが望むものを何でも注入できるので、恐ろしいアイデアであることを知っています(または少なくとも私はそう思います)$1

だから...これに対処する最良の方法は何ですか?インジェクション攻撃に対して広く開かれていないときに、root権限でjoeに必要なことをさせ、変数を渡す(または環境変数を使用して効果的に行う)ようにするにはどうすればよいですか?

回答:


14

環境をリセットするように構成されている場合、シェルスクリプトを実行してsudoも安全です。逆に、環境をリセットしないと、スクリプトがそのパラメーターを使用しない場合でも、シェルスクリプトを実行することは安全ではありません(シェルスクリプトでsetuid許可するを参照)。があること、またはこのオプションがコンパイル時のデフォルトであることを確認してください(を含める必要があります)。sudosudoDefaults env_reset/etc/sudoerssudo sudo -V | grep envReset the environment to a default set of variables

スクリプトパラメータを使用することに特別な危険はありません。$1文字列です。確認する必要があるのは、文字列として使用していることだけです。(たとえば、しないでくださいeval "$1"。)明らかに、ここでは、変数の内容について想定しないこと、およびすべての変数置換を二重引用符で囲むことが重要です(つまり"$1"、ではなく、書き込み$1)。変数置換を二重引用符で囲むことは、特権を使用して実行されるスクリプトに固有のものではなく、常に実行する必要があることに注意してください。

udhcpcホスト名のように見えないものをどう処理するかに応じて、パラメーターをさらに検証することができます。たとえば、これは最初の構文チェックを実行します。

#!/bin/sh
case "$1" in
  *[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"

そのコマンドの動作に影響を与える可能性のある他の考慮事項:現在の作業ディレクトリ、および標準入力、標準出力、標準エラー出力が指すもの、シグナルハンドラとulimit。たとえば、コアダンプ(<kbd> Ctrl-\ </ kbd>)を許可することにより、ユーザーがシステム上で非常に制限されたサイズのtmpfsであり、DoSを許可する可能性がある/ run / lockをポイ捨てできます。
ステファンシャゼル

5

渡された入力を既知の適切なパターンと照合する必要があります。

たとえば、IPアドレスが有効な入力である可能性があります。したがって、次のようなものを使用できます。

if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
  udhcpc -b -i eth0 -h "$1"
else
  echo "Don't mess with me pork chop."
fi

正規表現はテストされていないことに注意してください。正規表現が危険なものを許可しないようにする責任があります。

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