请看下面的代码,它使用一些参数调用一个程序(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"
来绕过它。 - 只要添加双引号,然后!仍然没有,不仅是这些只是简单的规避,但那些甚至容易路径globbing/扩展。
- 然后在调用Groovy字符串插值之前在输入字符串两边加上引号。同样的,shell命令行没有改变。
- 然后,添加单引号,但在字符串中的每个单引号前面加上一个反斜杠,以防止shell将其解释为 meta字符。是的,如果我也用第二个反斜杠转义每个现有的反斜杠,这种方法是有效的。不过,如何防止这种扩展的细节有点取决于shell(POSIX式,Windows
bat
,不确定powershell)。而且,每个参数都需要三行代码。另外,如果没有显式的shebang行,我甚至不能确定使用了哪个shell。
我的问题是:Groovy中的内置函数在哪里,它以一种可移植的、与shell无关的方式为我完成了这一任务?我很难相信它不存在,但我却找不到它。而且,我是第一个遇到这个问题的人,这让我很困惑...
1条答案
按热度按时间rfbsl7qr1#
您所描述的内容称为 * 参数注入 *(引用为CWE-88),它是 * 命令注入 *(引用为CWE-77)的子类:
这些CWE中描述的一些潜在缓解措施包括:
您问题的答案:
Groovy中的内置函数在哪里,它以一种可移植的、与shell无关的方式为我完成了这一任务?
是:没有这样内置Groovy函数。
你应该做的是:
1.尽可能避免使用带有用户输入数据的shell脚本,而使用Groovy函数。
1.通过仅允许字母数字字符来使用输入验证。
1.使用How to prevent command injection through command options?中讨论的引号。这是一个不太安全的选项,因为
sh
Jenkins命令使用系统默认shell(可以是任何内容),并且不能100%保证没有绕过此引号的技巧。