Jest to podobne pytanie , które zajmuje się „owijania” scenariusza, w którym chcesz zastąpić na przykład cd
z poleceniem, która wywołuje polecenie wbudowane cd
.
Jednak w świetle shellshocka i innych oraz wiedząc, że bash importuje funkcje ze środowiska, przeprowadziłem kilka testów i nie mogę znaleźć sposobu, aby bezpiecznie wywołać wbudowaną wersję cd
z mojego skryptu.
Rozważ to
cd() { echo "muahaha"; }
export -f cd
Wszelkie skrypty wywoływane w tym środowisku za pomocą cd
ulegną awarii (weź pod uwagę skutki czegoś takiego cd dir && rm -rf .
).
Istnieją polecenia sprawdzające typ polecenia (wygodnie wywoływanego type
) oraz polecenia do wykonania wbudowanej wersji, a nie funkcji ( builtin
i command
). Ale oto oto można je również zastąpić za pomocą funkcji
builtin() { "$@"; }
command() { "$@"; }
type() { echo "$1 is a shell builtin"; }
Przyniesie następujące:
$ type cd
cd is a shell builtin
$ cd x
muahaha
$ builtin cd x
muahaha
$ command cd x
muahaha
Czy jest jakiś sposób, aby bezpiecznie zmusić bash do użycia wbudowanego polecenia, lub przynajmniej wykryć, że polecenie nie jest wbudowane, bez czyszczenia całego środowiska?
Zdaję sobie sprawę, że jeśli ktoś kontroluje twoje środowisko, prawdopodobnie i tak masz problemy, ale przynajmniej w przypadku aliasów masz opcję, aby nie wywoływać aliasu poprzez wstawienie \
przed nim.
env
polecenia, w ten sposób:env -i <SCRIPT.sh>
env
nie jest również zdefiniowane jako funkcja. To jest przerażające. Najpierw pomyślałem, że pomogą znaki specjalne - dzwonienie z pełną ścieżką, która obejmuje/
, używanie.
źródła i tak dalej. Ale można ich również używać do nazw funkcji! Państwo może na nowo zdefiniować dowolną funkcję, którą chcesz, ale trudno wrócić do wywoływania oryginalnego polecenia.#/bin/sh
jeśli nie jest to domyślna powłoka interaktywna.Odpowiedzi:
Olivier D jest prawie poprawny, ale musisz ustawić
POSIXLY_CORRECT=1
przed uruchomieniemunset
. POSIX ma pojęcie specjalnych wbudowanych i bash to obsługuje .unset
jest jednym z takich wbudowanych. SzukajSPECIAL_BUILTIN
wbuiltins/*.c
w źródle bash na liście, zawieraset
,unset
,export
,eval
isource
.Rogue
unset
został usunięty ze środowiska, jeśli rozbroićcommand
,type
,builtin
to powinieneś być w stanie kontynuować, aleunset POSIXLY_CORRECT
jeśli opierając się na nie-POSIX zachowań lub zaawansowanych funkcji bash.Nie dotyczy to jednak aliasów, więc musisz użyć,
\unset
aby upewnić się, że działa w interaktywnej powłoce (lub zawsze, jeśliexpand_aliases
jest to możliwe).Myślę, że dla paranoika powinno to wszystko naprawić:
(
while
,do
,done
I[[
są zarezerwowane słowa i nie wymagają ostrożności.) Uwaga używamyunset -f
, aby mieć pewność, aby funkcje ustawione, chociaż zmienne i funkcje dzielić tę samą przestrzeń nazw jest możliwe zarówno istnieć jednocześnie (dzięki Etan Reisnera), w którym to przypadku dwukrotne rozbrojenie również załatwi sprawę. Państwo może zaznaczyć funkcję tylko do odczytu, bash nie przeszkadza Ci wyłączające tylko do odczytu funkcji włącznie bash-4.2, bash-4.3 nie przeszkadza wam, ale nadal honoruje specjalnych poleceń wbudowanych, gdyPOSIXLY_CORRECT
jest ustawiony.Tylko do odczytu
POSIXLY_CORRECT
nie jest prawdziwym problemem, nie jest to logiczna wartość ani flaga oznacza, że jego obecność włącza tryb POSIX, więc jeśli istnieje tylko do odczytu, możesz polegać na funkcjach POSIX, nawet jeśli wartość jest pusta lub 0. Musisz po prostu rozbrajaj problematyczne funkcje w inny sposób niż powyżej, być może z pewnymi wycięciami:(i zignoruj wszelkie błędy) lub zaangażuj się w inne skryptobatyki .
Inne notatki:
function
jest słowem zastrzeżonym, można je aliasować, ale nie można przesłonić funkcją. (Aliasingfunction
jest raczej kłopotliwy, ponieważ\function
nie można go ominąć)[[
,]]
są słowami zastrzeżonymi, można je aliasować (które zostaną zignorowane), ale nie można ich przesłonić funkcją (chociaż funkcje można tak nazwać)((
nie jest prawidłową nazwą funkcji ani aliasemźródło
unset
et al przed nadpisaniem.-f
argumentu,unset
prawda? W przeciwnym razie, jeśli zdefiniowana jest zarówno zmienna, jak i funkcja o tej samej nazwie, co wbudowane, najpierwunset
wybierze zmienną do rozbrojenia. To również nie powiedzie się, jeśli ustawiono którąś z ukrytych funkcji,readonly
prawda? (Chociaż jest to wykrywalne i może zostać popełnione fatalny błąd). Również to pomija[
wbudowane wydaje się.\unset -f unset
miało to sens, biorąc pod uwagę, że zostanie to wykonane w pętli odczytu. Jeśliunset
jest funkcją\unset
, normalnie rozwiążesz ją zamiast wbudowanej, ale możesz używać jej\unset
bezpiecznie, dopóki działa tryb POSIX. Jawne wywołanie\unset -f
na[
,.
i:
może być dobrym pomysłem, choć, jak swoimi regex wyłącza je. Dodałbym również-f
do\unset
pętli i\unset POSIXLY_CORRECT
po pętli, zamiast wcześniej.\unalias -a
(po\unset -f unalias
) pozwala również bezpiecznie zrezygnować z ucieczki przy kolejnych poleceniach.[[ ${POSIXLY_CORRECT?non-POSIX mode shell is untrusted}x ]]
spowoduje to, że skrypt nieinteraktywny zakończy działanie z błędem wskazanym, jeśli zmienna jest rozbrojona, lub kontynuuje, jeśli zostanie ustawiona (pusta lub dowolna wartość).\unset
” ... Należy zauważyć, że cytowanie dowolnego znaku (-ów) działałoby by uniknąć rozszerzenia aliasu, a nie tylko pierwszego.un"se"t
działałby równie dobrze, ale mniej czytelny. „Pierwsze słowo każdego prostego polecenia, jeśli nie jest cytowane, jest sprawdzane pod kątem aliasu”. - Ref. BashTak to. Jeśli uruchomisz skrypt w nieznanym środowisku, wszystko może się nie udać, zaczynając od
LD_PRELOAD
spowodowania, że proces powłoki wykona dowolny kod, zanim jeszcze przeczyta twój skrypt. Próba ochrony przed wrogim środowiskiem z wnętrza skryptu jest daremna.Sudo od ponad dekady odkaża środowisko, usuwając wszystko, co wygląda jak definicja funkcji bash. Od czasu Shellshock inne środowiska, w których działa skrypt powłoki w niezaufanym środowisku, postępują podobnie.
Nie można bezpiecznie uruchomić skryptu w środowisku ustawionym przez niezaufany byt. Martwienie się o definicje funkcji nie jest produktywne. Odkaż swoje środowisko, a robiąc to zmienne, które bash interpretowałby jako definicje funkcji.
źródło
/bin/cat
chroot może wywoływać cokolwiek). Odkażanie środowiska daje poczucie rozsądkuPATH
(zakładając, że robisz to dobrze). Nadal nie rozumiem, o co ci chodzi.Możesz użyć
unset -f
do usunięcia wbudowanych funkcji, polecenia i typu.źródło
unset() { true; }
zajmuje się tym.