apache commons CommandLine对象是否可以防止命令行注入?

时间:2011-06-14 00:33:42

标签: java command-line apache-commons apache-commons-exec

我想使用org.apache.commons.exec Java库来调用可执行文件。 CommandLine对象是否可以防止命令行注入?例如,如果我打电话:

String singleStringArgument = "-whatever;rm -rf ~/*"; // evil looking argument!
CommandLine cl = new CommandLine(new File(pathToExe,exeName)); 

cl.addArgument(singleStringArgument);  // oh no!

Executor exe = new DefaultExecutor();
exe.execute(cl);
除了预期的命令之外,

rm -rf ~/*还会运行吗?如果确实如此,那么防止这种情况的最佳方法是什么?

API说addArgument()“处理引用”但我不确定在这种情况下这意味着什么。我可以用一个测试用例来看看我的linux盒子上发生了什么,但我想确保它在其他平台上也是安全的。

3 个答案:

答案 0 :(得分:4)

;是shell的一个功能。如果你没有在sh -c或类似的地方创建一个命令行,你就无法注入。并不是公共资源是安全的,而是你甚至没有运行具有可视性的程序。

Commons CLI正在包装Process类。未记录Process类以启动shell。记录下来的是exec,其中包含您告诉它的指定参数。

根据评论,开源的一个奇迹是你可以阅读源代码。如果commons-CLI的版本X执行您喜欢的操作,请依赖它,并且不进行重新检查就不升级。

答案 1 :(得分:1)

所以你控制命令(pathToExe)并且只担心参数?你对这个命令有多了解?它是否有可能执行另一个程序?即使没有调用辅助命令,它是否有可能做一些破坏性的事情?该程序是否有任何其他漏洞(缓冲区溢出等)?

作为一般答案,这种方法对我来说似乎很不错,特别是如果你想让它跨平台工作的话。如果您知道要执行的命令并且可以约束输入,那么您可能会发出吱吱声,但我个人不会使用此方法,除非有充分的理由这样做。

答案 2 :(得分:0)

我的建议是尽可能使程序在安全方面犯错,并且只发出命令本身而不是愚蠢地执行命令片段或传递最终用户发出的参数。注射有很多种。 ;已经讨论过了。你也可以使用反引号(在反引号中包裹rm -rf ~/*使shell首先解释它)用户也可以无意或有意地调用别名。可能出错的事情清单是无穷无尽的。