Bash 为防止外壳注入而逃逸

Bash 为防止外壳注入而逃逸,bash,shell,batch-file,escaping,code-injection,Bash,Shell,Batch File,Escaping,Code Injection,我需要从嵌入到另一个Mac/Windows应用程序中的Lua解释器运行一些shell命令,在这个应用程序中,shell命令是实现某些事情的唯一方法,比如在浏览器中打开帮助页。如果我有一个参数列表(这可能是用户输入的结果),我如何能避开每个参数以避免麻烦 受一个简单解决方案的启发,在类Unix系统上使用\,在Windows上使用^时,似乎可以转义所有非字母数字字符。据我所知,这防止了任何争论会导致 由于插入换行符,,执行另一个命令(Unix)或&(Windows) 在Unix上使用$或` 在具有

我需要从嵌入到另一个Mac/Windows应用程序中的Lua解释器运行一些shell命令,在这个应用程序中,shell命令是实现某些事情的唯一方法,比如在浏览器中打开帮助页。如果我有一个参数列表(这可能是用户输入的结果),我如何能避开每个参数以避免麻烦

受一个简单解决方案的启发,在类Unix系统上使用
\
,在Windows上使用
^
时,似乎可以转义所有非字母数字字符。据我所知,这防止了任何争论会导致

  • 由于插入换行符,
    ,执行另一个命令(Unix)或
    &
    (Windows)
  • 在Unix上使用
    $
    `
  • 在具有
    %
  • 使用
此外,在各自平台上用作转义字符的任何字符都将被正确转义

对我来说,这似乎是合理的,但有没有什么我可能错过的陷阱?我知道在bash中,
\
后跟换行符将有效地删除换行符,这在这里不是问题

编辑

我的结论是:没有一种机制可以通过交换转义字符同时在Windows和*nix上工作。事实证明,要确保Windows程序真正看到我们希望它看到的命令行参数并不是那么简单,因为将命令字符串拆分为Windows上的参数不是由shell处理的,而是由被调用的程序本身处理的

因此,需要考虑两层逃逸:

  • 首先,Windows shell将处理我们提供给它的内容。它可能做的是在
    %
    处进行变量替换,在
    &
    处拆分为多个命令,或者在
    |
    处连接到另一个命令
  • 然后,它将把一个命令字符串交给被调用的程序,该程序将分割该命令字符串,理想情况下,但不一定遵循命令字符串

  • 假设它遵循这些规则,我们可以逆向工作,首先转义到这些规则,然后再转义到shell。

    使用动态参数调用子进程容易出错和危险,而且许多语言都没有提供良好的机制来保护开发人员。例如,在Python中,不再推荐使用该模块,而是提供了一种适当的机制来安全地进行系统调用。特别是,您可以传递
    subprocess.run()
    参数列表,而不是单个字符串,从而避免了首先需要实现任何容易出错的转义

    快速搜索类似于
    子流程的Lua工具,该工具似乎没有得到积极开发,但可能比自己尝试实现正确的转义要好

    如果必须这样做,请查看()的Python代码—它正确地转义了一个输入字符串,以便“在shell命令行中”使用:


    你应该能够在Lua中复制这一点。

    这就是为什么你不应该被一个显然不熟悉bash的人写的随机博客文章“启发”的原因。你应该做的是RTFM:你会意识到用反斜杠引用所有东西不仅是过火,实际上还有一个例外,也就是说,你所做的是错误的。你应该做的是用
    '\''
    替换每一个引号,然后用单引号将整个事情包装起来,然后用它来完成。顺便说一句,我特别对bash进行了评论。在同一个问题中询问bash和cmd并不是一个好主意。您将使用什么类型的windows batch或linux bash系统?解决方案完全不同在类Unix系统上创建进程,Windows则完全不同:类Unix系统使用
    execve
    单独传递参数,而Windows在单个命令行字符串中传递参数。尽管Windows上有解析命令行的指南和内置实用程序,但每个程序都可以制定自己的命令行解析规则。看看和。你为什么用贝壳?
    # use single quotes, and put single quotes into double quotes
    # the string $'b is then quoted as '$'"'"'b'
    return "'" + s.replace("'", "'\"'\"'") + "'"