文字列変数によるシェルコマンドの保護


9

プログラミング言語内で、単純なシェルコマンドを実行します

cd var; echo > create_a_file_here

varが、私は、ファイル「create_a_file_here」を作成したい場所に(たぶん)ディレクトリの文字列を含む変数であること。これで、誰かがこのコード行を見つけた場合、たとえば、次のコードを割り当てることにより、コードを悪用することが可能です。

var = "; rm -rf /"

物事はかなり醜くなります。上記のケースを回避する1つの方法は、「;」などの特殊文字をvarの文字列で検索することです。シェルコマンドを実行する前に、これはおそらくすべてのエクスプロイトをカバーしているとは思いません。

「cd var」がディレクトリのみを変更し、それ以外は変更しないようにするための良い方法を知っている人はいますか?


4
シェルを呼び出す方法に応じvarて、引数として渡すこともできます。例えば、呼び出しshの引数で-c'cd "$1"; echo > create_a_file_here''sh'var作品やへの変更を必要としませんvar'sh'引数は次のように渡されます$0
ipsec

1
どのプログラミング言語?あなたはPOSIXを使用しているsh、または同様の構文を使用して独自のプログラミング言語を作成するが、拡張するvar代わりに、あなたが書くために必要なのcd "$var"?それともこれbashshopt -s cdable_vars?ああ、私はあなたが他のいくつかのプログラムがこれらのコマンドを実行するためにシェルをフォークすることを意味すると思います。したがって、引用するだけですvarが、引用文字自体が含まれていないことを確認してください...
Peter Cordes '10

@PeterCordes Bashの場合は、二重引用符を含む二重引用符で囲まれた変数で問題ありません。例:s='"'; echo "$s"プリント"
wjandrea 2018年

@WJAndrea:はい。ただし、信頼できない入力から変数の割り当てを構築するときに無効にできない「切り札」の引用はありません。ああ、解決策:var=untrusted string親プログラムで行うのでvar、を呼び出すときにすでに設定されている環境変数もそうですsh。次に、展開するたびにそれを引用するだけでよく、確実に行うことができます。ああ、そのアイデアはすでにステファンの答えの一部だと思います>。<
Peter Cordes

回答:


9

私が正しく理解していればvar、プログラミング言語の変数です。

そして、あなたのプログラミング言語では、あなたはシェルに"cd "、とその変数との内容を連結した文字列を解釈するように要求しています"; echo > create_a_file_here"

その場合、はい、の内容がvar厳しく制御されていなければ、コマンドインジェクションの脆弱性です。

シェルの構文で変数の内容を適切に引用して、cd組み込み関数に単一の引数として渡されることが保証されるようにすることができます。

別のアプローチは、その変数の内容を別の方法で渡すことです。明白な方法は、それを環境変数に渡すことです。たとえば、Cの場合:

char *var =  "; rm -rf /";
setenv("DIR", var, 1);
system("CDPATH= cd -P -- \"$DIR\" && echo something > create_a_file_here");

今回は、シェルに解釈を依頼するコードは修正されていますが、シェルの構文で適切に記述する必要があります(ここではPOSIX準拠のシェルであると想定しています)。

  • シェル変数展開は、split + globを防ぐために引用符で囲む必要があります
  • あなたは簡単なことをする-Pためcdに必要ですchdir()
  • (または一部のシェル)--でのvar開始に関する問題を回避するために、オプションの終わりをマークする必要があります-+
  • CDPATH環境にある場合に備えて、空の文字列に設定します
  • 成功したecho場合のみコマンドを実行cdします。

ある1つの残りの問題(少なくとも)次の場合var-、それはというディレクトリにchdirしていない-だけに、前(に格納されているディレクトリ$OLDPWD)とOLDPWD=- CDPATH= cd -P -- "$DIR"、それを回避するには保証されません。したがって、次のようなものが必要になります。

system(
  "case $DIR in\n"
  " (-) CDPATH= cd -P ./-;;\n"
  " (*) CDPATH= cd -P -- \"$DIR\";;\n"
  "esac && ....");

¹ちょうどやってすることに注意system(concat("cd \"", var, "\"; echo..."));されていない移動するための方法は、あなただけの問題を移動すると思います。

たとえば、var = "$(rm -rf /)"まだ問題があります。

唯一のボーンのようなシェルの引用テキストへの信頼性の高い方法は、単一引用符を使用することですし、また、文字列中に発生する可能性が単一引用符の世話をします。例えば、オンchar *var = "ab'cd"にしますchar *escaped_var = "'ab'\\''cd'"。つまり、すべて'をに置き換え'\''、全体をにラップし'...'ます。

それはまだその引用符で囲まれた文字列は、バッククォート内で使用されていないことを前提としていて、あなたはまだ必要があるだろう---P&&CDPATH=...


12

簡単な解決策:プログラムからシェルを呼び出さないでください。全然。

ここでの例は簡単です。ディレクトリの変更とファイルの作成は、どのプログラミング言語でも簡単です。ただし、外部コマンドを実行する必要がある場合でも、通常はシェルを介して実行する必要はありません。

したがって、たとえばPythonでは、を実行os.system("somecmd " + somearg)する代わりにを使用しますsubprocess.run(["somecmd", somearg])。Cでは、の代わりにandをsystem()使用fork()しますexec()(またはそれを行うライブラリを見つけます)。

シェルを使用する必要がある場合は、コマンドライン引数を引用するか、ステファンの回答のように環境に渡します。あなた自身が特殊文字の心配を見つける場合にも、正しい解決策をしているではない(ブラックリスト)を除外するために潜在的に危険な文字を試してみてください、だけしておく(ホワイトリスト)安全であることが知られている文字を。

機能がわかっているキャラクターのみを許可してください。そうすることで、何かを見落とすリスクが少なくなります。最終結果は[a-zA-Z0-9_]、を許可することだけを決定することになるかもしれませんが、それは仕事を完了するのに十分なだけかもしれません。また、あなたのロケールとツールセットのようなアクセント付き文字含まれていないことをチェックすることもできますäし、öその中を。それらはおそらくどのシェルからも特別なものとは考えられていませんが、パスするかどうかを確認することをお勧めします。


1
また、照合に使用する[a-zA-Z0-9]ものには、一部のロケールのà一部のシェル(などbash)でエンコーディングが誤って解釈される可能性があるようなものが含まれていないことを確認してください。
ステファンChazelas

@StéphaneChazelas(興味がない:)それらは(そしてそれらの影響を受けるロケールのすぐ下にありますか)
Wilf

10

プログラミング言語内では、シェルコマンドを実行するよりも優れた方法があるはずです。たとえばcd var、プログラミング言語に相当するものに置き換えるとchdir (var);、値がのトリックvarだけで、意図しない、場合によっては悪意のあるアクションではなく、「ディレクトリが見つかりません」というエラーが発生します。

また、ディレクトリを変更するのではなく、絶対パスを使用できます。使用するディレクトリ名、スラッシュ、ファイル名を連結するだけです。

Cでは、私は次のようなことをするかもしれません:

char filepath[PATH_MAX];  /* alternative constant: MAXPATHLEN */

/* Join directory name in var and the filename, guarding against exceeding PATH_MAX */
snprintf (filepath, PATH_MAX, "%s/%s", var, "create_a_file_here");

/* create an empty file/truncate an existing one */
fclose (fopen (filepath, "w") );

確かにあなたのプログラミング言語は同じようなことをすることができますか?


回答ありがとうございます。残念ながら、bashコマンドで回避策を使用する必要があります。私は変数を引用することをテストしました-muruが示唆したように-それはうまくいくようです!
ES___ 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.