如何避免 Jenkins shell 调用中的代码注入?
考虑以下代码,它使用一些参数调用程序 (echo
):
String malicious_input = '""; rm -rf / #yikes'
sh "echo Hello ${malicious_input}!"
生成的 shell 脚本是
echo Hello ""; rm -rf / #yikes!
简单、经典的代码注入。没有什么闻所未闻的。我一直在努力寻找妥善处理此案的方法。解决此问题的第一种方法是:
- 只需在 shell 调用中的字符串周围添加单引号,例如
sh "echo Hello '${malicious_input}'!"
。是的,但不是,我只需要切换到malicious_input = "'; rm -rf / #yikes"
即可避免这种情况。 - 那么只需添加双引号即可!仍然不,这些不仅很容易规避,而且甚至容易发生路径通配/扩展。
- 然后在调用 Groovy 字符串插值之前在输入字符串周围添加引号。同样的事情,shell 命令行没有改变。
- 然后,添加单引号,但在字符串内的每个单引号前面加上反斜杠,以防止 shell 将其解释为元字符。是的,如果我也用第二个反斜杠来转义每个现有的反斜杠,那么这种方法就有效。尽管如此,如何防止这种扩展的细节在一定程度上取决于 shell(POSIX-ish、Windows
bat
,不确定 powershell)。此外,每个参数都需要三行代码。另外,如果没有明确的 shebang 行,我什至无法确定使用的是哪个 shell。
所以,我的问题是:Groovy 中以可移植、与 shell 无关的方式为我执行此操作的内置函数在哪里?我很难相信这不存在,但我找不到它。另外,我是第一个遇到这个问题的人,这让我很困惑......
Consider the following code, which invokes a program (echo
) with some arguments:
String malicious_input = '""; rm -rf / #yikes'
sh "echo Hello ${malicious_input}!"
The resulting shell script is then
echo Hello ""; rm -rf / #yikes!
Simple, classic code injection. Nothing unheard. What I have been struggling to find is a way to properly handle this case. First approaches to fix this are:
- Just add single quotes around the string in the shell call, like
sh "echo Hello '${malicious_input}'!"
. Yes, but no, I only need to switch tomalicious_input = "'; rm -rf / #yikes"
to circumvent that. - Just add double quotes then! Still no, not only are these just as simple to circumvent but those are even prone to path globbing/expansion.
- Then add the quotes around the input string before invoking Groovy string interpolation. Same thing, the shell commandline is unchanged.
- Then, add single quotes but prefix every single quote inside the string with a backslash to prevent its interpretation as meta character by the shell. Yes, that kind-of works, if I also escape every existing backslash with a second one. Still, the details of how to prevent this expansion depend a bit on the shell (POSIX-ish, Windows
bat
, not sure about powershell). Also, this takes three lines of code for every argument. Plus, without an explicit shebang line, I can't even be sure which shell is taken.
So, my question is this: Where is the built-in function in Groovy that does this for me in a portable, shell-agnostic way? I find it hard to believe that this doesn't exist, yet I can't find it. Also, quite puzzling for me that I'm the first one to come across this issue...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您所描述的称为参数注入,引用为CWE-88 是命令注入的子类,引用为 CWE-77:
这些 CWE 中描述的一些潜在缓解措施包括:
你的问题的答案:
是: 没有这样的内置 Groovy 函数。
您应该做的是:
sh
Jenkins 命令使用系统默认 shell(可以是任何东西),并且不能 100% 保证不存在绕过此引用的技巧。What you are describing is called Argument Injection referenced as CWE-88 which is a subclass of Command Injection referenced as CWE-77:
Some potential mitigations described in these CWEs are:
The answer to your question:
is : there is no such built-in Groovy function.
What you should do is:
sh
Jenkins command use the the system default shell (which can be anything) and there is no 100% guarantee that there is no tricks to bypass this quoting.