この質問は完全に一般的なものであり、私の場合にのみ適用されるものではありません。私は小さなビジボックスデバイスを持っていて、root以外のユーザーがroot権限で特定のスクリプトを実行できるようにしたいです。たとえば、DHCP を有効にする次のような小さなスクリプトがあります。ここで$1
cmdline(!!) に送信される唯一の変数は、転送するホスト名です。
#!/bin/bash
udhcpc -b -i eth0 -h $1
/etc/sudoers
udhcpcをこのように実行するにはrootアクセスが必要なので、次の行を含めるように変更する予定です。
joe ALL = NOPASSWD: /path/to/enable_dhcp.sh
これにより、「joe」は以下を実行してroot権限でスクリプトを簡単に実行できます。
sudo /path/to/enable_dhcp.sh
そしてパスワードを聞かないでください(私はJoeがこのスクリプトを書くことができるようにしたいので、パスワードが欲しいです)。
今私知る(または少なくとも私の考えでは)$1
root権限で簡単に実行できるスクリプトで使用するのは恐ろしいアイデアです。欲しいものは何でも挿入できるからです。
だから...この問題を処理するための最良の方法は何ですか?注入攻撃に対して脆弱ではなく、Joeがroot権限で目的の操作を実行して変数を渡すことができるようにする(または環境変数を使用するのと同じくらい効率的に)、どうすればよいですか?
答え1
以下のシェルスクリプトを実行するのはsudo
安全です前提は、sudo
環境をリセットするように構成されていることです。。逆に、sudo
スクリプトが引数を使用しなくても環境をリセットせずにシェルスクリプトを実行するのは安全ではありません(参照:シェルスクリプトでsetuid設定を許可する)。このオプションDefaults env_reset
が/etc/sudoers
コンパイル時のデフォルト値であることを確認してください(sudo sudo -V | grep env
含める必要がありますReset 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"
答え2
渡された入力を既知の良好なパターンと一致させる必要があります。
たとえば、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
この正規表現はテストされておらず、正規表現が危険なものを許可しないことを確認するのはあなたの責任です。