从 C 程序中,我想以文件名作为参数调用 shell 脚本。用户可以控制文件名。C 类似于(省略初始化/错误检查):
sprintf(buf, "/bin/sh script.sh \"%s\"", filename);
system(buf);
目标设备实际上是一个嵌入式系统,所以我不需要担心恶意用户。显然,这将是 Web 环境中的攻击媒介。尽管如此,如果系统上有一个文件名,例如,其名称中包含反引号,则该命令将失败,因为 shell 将对名称执行扩展。有什么可以防止命令替换吗?
从 C 程序中,我想以文件名作为参数调用 shell 脚本。用户可以控制文件名。C 类似于(省略初始化/错误检查):
sprintf(buf, "/bin/sh script.sh \"%s\"", filename);
system(buf);
目标设备实际上是一个嵌入式系统,所以我不需要担心恶意用户。显然,这将是 Web 环境中的攻击媒介。尽管如此,如果系统上有一个文件名,例如,其名称中包含反引号,则该命令将失败,因为 shell 将对名称执行扩展。有什么可以防止命令替换吗?
好吧,您总是可以通过调用 fork() 然后 execv() 来重新实现 system()。
http://www.opengroup.org/onlinepubs/000095399/functions/system.html
尝试在系统函数中触发“unalias”。
由于您将此标记为 CI 将为您提供 C 答案。您需要对文件名进行转义——创建一个新字符串,shell 将正确处理该字符串,以便This is a file name
生成This\ is\ a\ file\ name
或bad;rm *;filename
变为bad\;rm\ \*\;filename
. 然后你可以将它传递给shell。
解决此问题的另一种方法是直接使用fork
其中一个exec
函数运行 shell。将参数直接传递给程序不会导致 shell 命令行扩展或解释。
正如 sharth 所说,你不应该使用system
butfork
和execv
你自己。但是要回答如何使字符串安全地传递到 shell 的问题(如果您坚持使用system
),您需要对字符串进行转义。最简单的方法是首先用(单引号,反斜杠,单引号,单引号)替换每个出现的'
(单引号),然后在字符串的开头和结尾添加(单引号)。另一种相当简单(但通常效率较低)的方法是在每个字符之前放置一个反斜杠,但是您仍然需要做一些特殊的引号技巧来处理嵌入的换行符,所以我更喜欢第一种方法。'\''
'