防止Shell注入的适当转义

7
我需要从嵌入在另一个Mac/Windows应用程序中的Lua解释器运行一些Shell命令,其中Shell命令是实现某些操作(例如在浏览器中打开帮助页面)的唯一途径。如果我有一系列参数(可能是用户输入的结果),该如何转义每个参数以避免出错?
this article启发,一个简单的解决方案似乎是转义所有非字母数字字符,在类Unix系统上使用\,在Windows上使用^。据我所知,这可以防止任何参数引起:
  • 由于干扰换行符、;(Unix)或 &(Windows)而执行另一个命令
  • 在Unix上使用$`进行命令替换
  • 在Windows上使用%进行变量评估
  • 重定向使用<|>
此外,任何在相应平台上作为转义字符有效的字符都将被正确转义。
这对我来说似乎很合理,但有没有我可能忽略的陷阱? 我知道在bash中,后跟换行符的 \\ 将有效地删除换行符,这在这里不是问题。 编辑 我的结论:没有单个机制可以通过交换转义字符在Windows和*nix上同时工作。 结果并不那么简单,因为要确保Windows程序实际上看到我们想要的命令行参数,需要处理Windows上的命令字符串拆分而不是由shell处理而是由所调用的程序本身处理。
因此,需要考虑两层转义:
  1. 首先,Windows shell将处理我们给出的内容。它可能会在%处进行变量替换,在&处拆分成多个命令或在|处将其传递给另一个命令。
  2. 然后,它将向调用的程序传递一个单个命令字符串,该程序将拆分该字符串,理想情况下但不一定遵循Microsoft描述的规则
假设遵循这些规则,就可以逆向操作,首先转义这些规则,然后进一步为shell转义。

3
顺便说一下,我特别是在评论bash。在同一个问题中询问bash和cmd并不是一个好主意。 - 4ae1e1
@ThomasW 对于批处理,被调用的程序也很重要。 - jeb
1
在类Unix系统和Windows上创建进程的方式是相当不同的:虽然类Unix系统使用execve,其中参数是单独传递的,但Windows则在单个命令行字符串中传递参数。尽管Windows有指导方针和内置实用程序来解析命令行,但每个程序都可以制定自己的命令行解析规则。请查看 https://blogs.msdn.microsoft.com/larryosterman/2007/10/03/the-windows-command-line-is-just-a-string/ 和 http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx。 - Gumbo
1
你为什么使用Shell? - Karoly Horvath
显示剩余12条评论
1个回答

4
使用动态参数调用子进程容易出错且危险,许多语言都没有提供良好的机制来保护开发者。例如,在Python中,不再推荐使用os.system(),而是subprocess模块提供了一个适当的机制来安全地进行系统调用。特别是,您传递给subprocess.run()一个列表的参数,而不是单个字符串,从而避免了需要在第一次实现任何容易出错的转义。
对于类似于subprocess的Lua工具的快速搜索发现了lua-subprocess,它似乎没有被积极开发,但仍可能比尝试自己实现适当的转义更好。
如果你必须这样做,请查看Python代码shlex.quote()源代码) - 它可以正确地转义输入字符串以在“shell命令行”中使用:
# use single quotes, and put single quotes into double quotes
# the string $'b is then quoted as '$'"'"'b'
return "'" + s.replace("'", "'\"'\"'") + "'"

你应该能够在Lua中复制它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接