次のJavaコードを使用するアプリケーションのコードをレビューしていて、exec()の使用がコマンドインジェクションの影響を受けやすいかどうかを知りたいと思っていました。
public class FindFileInDir {
public static void main(String[] args){
try {
Runtime rt = Runtime.getRuntime();
String[] cmdArr = { "bash", "checkfileindirectory.sh", "<directory_to_search>", "<file_to_find>" };
Process p = rt.exec(cmdArr);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
コンテキストを提供するために、シェルスクリプトはディレクトリ内のファイルを検索するfindコマンドのラッパーにすぎません。 2つの引数directory_to_searchおよびfile_to_findを取ります。スクリプトへのdirectory_to_search引数は修正されていますが、ユーザーにはfile_to_find引数が含まれています。このシナリオで複数のbashコマンドをチェーンするために使用できるペイロードはありますか?
次のようなcheckfileindirectory.sh
にリンクされたプログラムを実行しました。
#!/bin/bash
echo $1 > param1.txt
echo $2 > param2.txt
テストとして、"<file_to_find>"
を"<file_to_find>;touch MikeWasHere.txt"
に変更しました
String[] cmdArr = { "bash", "checkfileindirectory.sh", "<directory_to_search>", "<file_to_find>;touch MikeWasHere.txt" };
そして私はこの出力を取得します:
➜ /tmp javac FindFileInDir.Java
➜ /tmp Java FindFileInDir
➜ /tmp cat param1.txt
<directory_to_search>
➜ /tmp cat param2.txt
<file_to_find>;touch MikeWasHere.txt
➜ /tmp ls MikeWasHere.txt
ls: cannot access 'MikeWasHere.txt': No such file or directory
したがって、それは次のようになりますJavaのrt.exec()は注入セーフです。
コマンドインジェクションに関するOWASPのページ には、Javaのexecに関する段落があります(強調は私のものです):
Cのシステム関数はその引数を解析するシェル(/ bin/sh)に渡しますが、Runtime.execは文字列を単語の配列に分割し、残りの単語をパラメーターとして配列の最初の単語を実行します。 。 Runtime.execはどの時点でもシェルを呼び出そうとはしません。主な違いは、シェルによって提供される機能の多くは、いたずら(「&」、「&&」、「|」、「||」などを使用してコマンドを連鎖させ、入力と出力をリダイレクトする)は、最初のコマンドに渡されるパラメーターとして単純に終了します。
これは、Javaのrt.exec()が注入セーフであるという私たちの実験と一致しているようです