groovy 如何避免Jenkins shell调用中的代码注入?

prdp8dxp  于 2022-11-01  发布在  Jenkins
关注(0)|答案(1)|浏览(220)

请看下面的代码,它使用一些参数调用一个程序(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无关的方式为我完成了这一任务?我很难相信它不存在,但我却找不到它。而且,我是第一个遇到这个问题的人,这让我很困惑...

rfbsl7qr

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%保证没有绕过此引号的技巧。

相关问题