Java から OS のプロセスを起動する際に、渡している引数等が安全であるかどうか確認する必要があるかチェックしてみた。
(1)Runtime クラスから Process を生成して実行してみる。
public class Main {
public static void main(String[] args) throws Exception {
Runtime r = Runtime.getRuntime();
Process p = r.exec("cmd.exe /c dir | grep \\.");
byte[] b = new byte[8192];
int n;
FileOutputStream stdout = new FileOutputStream("stdout.txt");
BufferedInputStream binstd = new BufferedInputStream(p.getInputStream());
while ((n = binstd.read(b)) != -1) {
stdout.write(b, 0, n);
}
stdout.close();
FileOutputStream stderr = new FileOutputStream("stderr.txt");
BufferedInputStream binerr = new BufferedInputStream(p.getErrorStream());
while ((n = binerr.read(b)) != -1) {
stderr.write(b, 0, n);
}
stderr.close();
}
}
結果、「.」を含むディレクトリだけが stdout.txt に表示された。
(2)ProcessBuilderを生成して、command で複数の引数を渡してみる。
public class Main {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder();
pb.command("cmd.exe", "/c", "dir", "|", "grep", "\\.");
pb.redirectOutput(new File("stdout.txt"));
pb.redirectError(new File("stderr.txt"));
pb.start();
}
}
結果、「.」を含むディレクトリだけが stdout.txt に表示された。
(3)結論
パイプが解釈されてしまうため、プロセスを生成するときは、コマンド文字列をチェックしなければいけないようだ。