Czy zawsze jest bezpiecznie używać „eval echo”?

20

Używanie evaljest często odradzane, ponieważ pozwala na wykonanie dowolnego kodu. Jeśli jednak użyjemy eval echo, wygląda na to, że reszta ciągu stanie się argumentem, echowięc powinno być bezpieczne. Czy mam rację?

Cyker
źródło
1
nie zawsze bezpieczne, możesz owinąć bombę widelcową lub paskudną rm -fR *
μολὼν.λαβέ
Być może jest to tylko eksperyment myślowy, ale jeśli tak naprawdę zamierzałeś to zrobić, aby przekazać mu wiele argumentów -n, możesz to zrobić za pomocą niecytowanej zmiennej, takiej jak echo $argumentslub jeśli $argumentsjest tablicą echo "${arguments[@]}". Korzystanie eval echojest bezcelowe, nawet jeśli były bezpieczne.
JoL,

Odpowiedzi:

40

Przeciwprzykład:

DANGEROUS=">foo"
eval echo $DANGEROUS

Arbitralne argumenty echomogłyby zrobić coś bardziej nikczemnego niż utworzenie pliku o nazwie „foo”.

Celada
źródło
6
Także DANGEROUS="hello;ls":, dla dowolnych poleceń zamiast ls.
Kusalananda
2
Ponadto: DANGEROUS='$(ls)'(może być konieczne użycie większej liczby znaków ucieczki).
wizzwizz4
Czy eval echo '"'"$DANGEROUS"'"'zadziała? Wygląda na to, że na goo.gl/L2pPQP
Ismael Miguel
@ IsmaelMiguel To nie działa dla przykładów wizzwizz, Cyker lub sorontar, ani dla czegokolwiek z podwójnymi cudzysłowami w łańcuchu (np DANGEROUS='">foo"'.).
Gordon Davisson
Cerować. Wydawało mi się, że znalazłem coś, co trochę pomogło
Ismael Miguel,
26

@Celada zapewniła doskonałą odpowiedź. Aby zademonstrować, evalże jest naprawdę zły, oto coś bardziej nikczemnego niż tworzenie pliku o nazwie „foo” :

DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"

I oczywiście może istnieć coś bardziej nikczemnego niż coś bardziej nikczemnego niż tworzenie pliku o nazwie „foo” .

Cyker
źródło
8
+1 za wykazanie, że cytowanie zmiennej jak "$THIS"zamiast zwykłego jej $THISużywania nie pomaga!
Celada,
Pomocne wydaje się przesłanie dodatkowej pary cytatów. Coś jak eval echo '"'"$DANGEROUS"'"'. Wypróbuj na goo.gl/L2pPQP
Ismael Miguel
W rzeczywistości twój przykład nie jest bardziej nikczemny >foo, ponieważ „tworzenie pliku o nazwie„ foo ”niekoniecznie jest tym wszystkim >foo. Jedyną prawdziwą różnicą w twoim przykładzie jest to, że nie pozostawia po sobie pustego pliku. Treści wciąż nie ma.
flarn2006
12

Nie, nie zawsze jest bezpiecznie. Ewaluacja może wykonać dowolne polecenie.

Bezpieczne polecenie, takie jak to (data nie jest wykonywana, ponieważ znajduje się w pojedynczych cudzysłowach):

$ echo '$(date)'
$(date)

Staje się niebezpieczny, jeśli jest używany z eval:

$ eval echo '$(date)'
Sat Dec 24 22:55:55 UTC 2016

Oczywiście data może być dowolną komendą.

Jednym ze sposobów, aby to poprawić, jest dodatkowo zacytowanie argumentów do oceny:

$ eval echo '\$(date)'
$(date)

Ale zwykle trudno jest poprawnie podać dwa razy wyrażenie.

I niemożliwe jest kontrolowanie poprawnego cytowania, jeśli wyrażenie może zostać ustawione przez zewnętrznego atakującego, na przykład:

$ var='$(date);echo Hello!'
$ eval echo "$var"
Sat Dec 24 23:01:48 UTC 2016
Hello!
sorontar
źródło
1

Chociaż prawdą jest, że evalzawsze należy podchodzić ostrożnie, eval echokonstrukcja nie zawsze jest bezcelowa i można z niej bezpiecznie korzystać. Ostatnio potrzebowałem go, aby uzyskać ocenę wielu rozszerzeń nawiasów w kolejności, w jakiej ich potrzebowałem.

bash wykonuje wiele rozszerzeń nawiasów od lewej do prawej, więc

xargs -I_ cat _/{11..15}/{8..5}.jpg

rozwija się do

xargs -I_ cat _/11/8.jpg _/11/7.jpg _/11/6.jpg _/11/5.jpg _/12/8.jpg _/12/7.jpg _/12/6.jpg _/12/5.jpg _/13/8.jpg _/13/7.jpg _/13/6.jpg _/13/5.jpg _/14/8.jpg _/14/7.jpg _/14/6.jpg _/14/5.jpg _/15/8.jpg _/15/7.jpg _/15/6.jpg _/15/5.jpg

ale najpierw potrzebowałem drugiego rozszerzenia nawiasu klamrowego, ustępując

xargs -I_ cat _/11/8.jpg _/12/8.jpg _/13/8.jpg _/14/8.jpg _/15/8.jpg _/11/7.jpg _/12/7.jpg _/13/7.jpg _/14/7.jpg _/15/7.jpg _/11/6.jpg _/12/6.jpg _/13/6.jpg _/14/6.jpg _/15/6.jpg _/11/5.jpg _/12/5.jpg _/13/5.jpg _/14/5.jpg _/15/5.jpg

Najlepsze, co mogłem wymyślić, żeby to zrobić

xargs -I_ cat $(eval echo _/'{11..15}'/{8..5}.jpg)

Działa to, ponieważ pojedyncze cudzysłowy chronią pierwszy zestaw nawiasów klamrowych przed rozwinięciem podczas analizowania evalwiersza poleceń, pozostawiając je do rozszerzenia przez wywołaną podpowłokę eval.

Może być jakiś sprytny schemat obejmujący zagnieżdżone rozszerzenia nawiasów klamrowych, który pozwala to zrobić w jednym kroku, ale jeśli jest, jestem za stary i głupi, aby to zobaczyć. Istnieją również inne powłoki, bashktóre pozwalają na bardziej uporządkowane sposoby osiągnięcia tego rodzaju rzeczy. Ale w każdym razie takie użycie evaljest bezpieczne, ponieważ wszystkie jego argumenty są stałymi ciągami znaków, które nie zawierają rozszerzeń parametrów.

flabdablet
źródło
Nie potrzebujesz tutaj echa i podstawiania poleceń (które również zależą od $ IFS). Mógłbyś zrobićeval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas
To też działa, ale powoduje, że proces podpowłoki jest odradzany przez eval, dopóki nie zostanie zakończony proces xargs; wersja eval echo sprawia, że ​​podpowłoka znika zanim jeszcze uruchomi się xargs. Jest to prawdopodobnie ważne tylko dla innych, którzy są tak analityczni jak ja w kwestii tego, co pojawia się w widokach drzewa htop i ustawia dzienniki -x :-)
flabdablet