Z podręcznika findutils:
Na przykład konstrukcje takie jak te dwa polecenia
# risky find -exec sh -c "something {}" \; find -execdir sh -c "something {}" \;
są bardzo niebezpieczne. Powodem tego jest rozszerzenie nazwy „{}” do nazwy pliku, która może zawierać średnik lub inne znaki specjalne dla powłoki. Jeśli na przykład ktoś utworzy plik,
/tmp/foo; rm -rf $HOME
dwie powyższe komendy mogą usunąć czyjś katalog domowy.Z tego powodu nie uruchamiaj żadnych poleceń, które przekażą niezaufane dane (takie jak nazwy plików) do poleceń, które interpretują argumenty jako polecenia do dalszej interpretacji (na przykład „sh”).
W przypadku powłoki istnieje sprytne obejście tego problemu:
# safer find -exec sh -c 'something "$@"' sh {} \; find -execdir sh -c 'something "$@"' sh {} \;
Takie podejście nie gwarantuje uniknięcia każdego problemu, ale jest znacznie bezpieczniejsze niż zastąpienie danych wybranego przez atakującego tekstem polecenia powłoki.
- Czy przyczyną problemu jest
find -exec sh -c "something {}" \;
to, że zamiennik{}
nie jest cytowany i dlatego nie jest traktowany jako pojedynczy ciąg? W rozwiązaniu
find -exec sh -c 'something "$@"' sh {} \;
,pierwszy
{}
jest zastępowany, ale skoro{}
nie jest cytowany, nie ma"$@"
również tego samego problemu co oryginalne polecenie? Na przykład,"$@"
zostanie rozszerzona"/tmp/foo;"
,"rm"
,"-rf"
, i"$HOME"
?dlaczego
{}
nie jest cytowany ani cytowany?
- Czy możesz podać inne przykłady (nadal z
sh -c
lub bez, jeśli dotyczy; z lub bez,find
które mogą nie być konieczne), w których stosuje się ten sam rodzaj problemu i rozwiązania, i które są minimalnymi przykładami, abyśmy mogli skupić się na problemie i rozwiązaniu za pomocą jak najmniej rozproszenia? Zobacz Sposoby dostarczania argumentów do polecenia wykonanego przez `bash -c`
Dzięki.