有没有办法阻止 sh/bash 执行命令替换?
我想从 C 程序中调用一个以文件名作为参数的 shell 脚本。用户可以控制文件名。 C 类似于(省略初始化/错误检查):
sprintf(buf, "/bin/sh script.sh \"%s\"", filename);
system(buf);
目标设备实际上是嵌入式系统,因此我不需要担心恶意用户。显然,这将是网络环境中的攻击媒介。尽管如此,如果系统上存在一个文件名(例如,其名称中包含反引号),则命令将失败,因为 shell 将对名称执行扩展。有什么办法可以防止命令替换吗?
From a C program I want to call a shell script with a filename as a parameter. Users can control the filename. The C is something like (initialization/error checking omitted):
sprintf(buf, "/bin/sh script.sh \"%s\"", filename);
system(buf);
The target device is actually an embedded system so I don't need to worry about malicious users. Obviously this would be an attack vector in a web environment. Still, if there is a filename on the system which, for example, contains backquotes in its name, the command will fail because the shell will perform expansion on the name. Is there any to prevent command substitution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,您始终可以通过调用 fork() 然后调用 execv() 来重新实现 system()。
http://www.opengroup.org/onlinepubs/000095399/functions/system.html
Well, you could always reimplement system() using a call to fork() and then execv().
http://www.opengroup.org/onlinepubs/000095399/functions/system.html
尝试在系统函数中触发“unalias”。
Try triggering "unalias " in the system function.
既然您将其标记为 CI,将为您提供 C 答案。您需要对文件名进行转义——创建一个由 shell 正确处理的新字符串,以便
This is a file name
生成This\ is\ a\ file\ name
或bad;rm *;filename
变为bad\;rm\ \*\;filename
。然后你可以将其传递给 shell。解决此问题的另一种方法是直接使用
fork
和其中一个exec
函数运行 shell。直接向程序传递参数不会导致 shell 命令行扩展或解释。Since you tagged this as C I will provide you with a C answer. You will need to escape the filename -- create a new string that will be treated properly by the shell, so that things like
This is a file name
producesThis\ is\ a\ file\ name
orbad;rm *;filename
becomesbad\;rm\ \*\;filename
. Then you can pass that to the shell.Another way around this would be to run the shell directly with
fork
and one of theexec
functions. Passing arguments directly to programs does not result in shell command line expansion or interpretation.正如 sharth 所说,您不应该使用
system
而应该自己使用fork
和execv
。但是要回答如何使字符串安全地传递到 shell 的问题(如果您坚持使用system
),您需要对字符串进行转义。最简单的方法是首先将每个出现的'
(单引号)替换为'\''
(单引号、反斜杠、单引号、单引号),然后在字符串的开头和结尾添加'
(单引号)。另一种相当简单(但通常效率较低)的方法是在每个字符之前放置一个反斜杠,但是您仍然需要执行一些特殊的引号技巧来处理嵌入的换行符,所以我更喜欢第一种方法。As sharth said, you should not use
system
butfork
andexecv
yourself. But to answer the question of how you make strings safe to pass to the shell (in case you insist on usingsystem
), you need to escape the string. The simplest way to do this is to first replace every occurrence of'
(single quote) with'\''
(single quote, backslash, single quote, single quote) then add'
(single quote) at the beginning and end of the string. The other fairly easy (but usually less efficient) method is to place a backslash before every single character, but then you still need to do some special quotation mark tricks to handle embedded newlines, so I prefer the first method.