考虑以下代码,该代码使用一些参数调用程序(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无关的方式为我做这件事?我很难相信这不存在,但我找不到它。此外,我是第一个遇到这个问题的人,这让我很困惑。。。
您所描述的被称为参数注入,被引用为CWE-88,这是命令注入CWE-77:的子类
这些CWE中描述的一些潜在缓解措施包括:
- 如果可能的话,使用库调用而不是外部进程来重新创建所需的功能
- (参数化(尽可能避免构建包含命令及其参数的单个字符串
- (输入验证(假设所有输入都是恶意的。使用";接受已知商品";输入验证策略,即使用严格符合规范的可接受输入列表。拒绝任何不严格符合规范的输入,或者将其转换为符合规范的内容
问题的答案:
Groovy中的内置函数在哪里,它以一种可移植的、与shell无关的方式为我做到了这一点?
是:没有这样的内置Groovy函数
你应该做的是:
- 尽可能避免在用户输入数据中使用shell脚本,而是使用Groovy函数
- 通过只允许使用字母数字字符来使用输入验证
- 使用引用,如"如何防止通过命令选项插入命令?"中所述?。这是一个不太安全的选项,因为
sh
Jenkins命令使用系统默认shell(可以是任何东西(,并且不能100%保证没有绕过此引用的技巧