Oto polecenie, którego użyłem do sprawdzenia powłoki bash pod kątem błędu Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Czy ktoś może szczegółowo wyjaśnić polecenie?
Oto polecenie, którego użyłem do sprawdzenia powłoki bash pod kątem błędu Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Czy ktoś może szczegółowo wyjaśnić polecenie?
Odpowiedzi:
Ta odpowiedź jest pochodną oryginalnego artykułu Matthew Miller na Fedorze Magazine , na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 .
Pozwól mi wyjaśnić:
env x='() { :;}; echo OOPS' bash -c :
Spowoduje to wydrukowanie „OOPS” w systemie podatnym na zagrożenia, ale zamknie się cicho, jeśli poprawiono bash.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
Spowoduje to wydrukowanie „OOPS” w systemie podatnym na zagrożenia, ale zostanie wydrukowane, “this is a test”
jeśli poprawiono bash.
Prawdopodobnie słyszałeś, że ma to coś wspólnego ze zmiennymi środowiskowymi. Ale dlaczego wykonywany jest kod w zmiennych środowiskowych? Cóż, tak nie powinno być - ale z powodu cechy, którą kusiłbym nazwać nieco sprytną dla własnego dobra, jest miejsce na wadę. Bash jest tym, co widzisz jako monit terminalowy, ale jest także językiem skryptowym i ma możliwość definiowania funkcji. Robisz to w ten sposób:
$ Ubuntu() { echo "Ubuntu is awesome."; }
a następnie masz nowe polecenie. Pamiętaj, że echo
tutaj jeszcze nie działa; jest po prostu zapisane, co stanie się, gdy uruchomimy nasze nowe polecenie. To będzie ważne za chwilę!
$ Ubuntu
Ubuntu is awesome.
Przydatny! Ale, powiedzmy, z jakiegoś powodu, musimy wykonać nową instancję bash jako podproces i chcemy w tym celu uruchomić moje nowe niesamowite polecenie. Instrukcja bash -c somecommand
robi dokładnie to: uruchamia podane polecenie w nowej powłoce:
$ bash -c Ubuntu
bash: Ubuntu: command not found
Och Smutny. Dziecko nie odziedziczyło definicji funkcji. Ale ma on nieodłączny wpływ na środowisko - zbiór par klucz-wartość, które zostały wyeksportowane z powłoki. (To jest cała koncepcja orzechów; jeśli nie jesteś z tym zaznajomiony, zaufaj mi na razie.) I, jak się okazuje, bash może również eksportować funkcje. Więc:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
Co jest w porządku i dobre - poza tym, że mechanizm, za pomocą którego można to osiągnąć, jest trochę podejrzany . Zasadniczo, ponieważ nie ma magii Linux / Unix do wykonywania funkcji w zmiennych środowiskowych, funkcja eksportu w rzeczywistości tworzy po prostu zwykłą zmienną środowiskową zawierającą definicję funkcji. Następnie, gdy druga powłoka odczytuje środowisko „przychodzące” i napotyka zmienną z zawartością, która wygląda jak funkcja, ocenia ją.
Teoretycznie jest to całkowicie bezpieczne , ponieważ pamiętaj, że zdefiniowanie funkcji tak naprawdę jej nie wykonuje . Z wyjątkiem - i właśnie dlatego tu jesteśmy - w kodzie wystąpił błąd, w którym ocena nie kończyła się po osiągnięciu końca definicji funkcji. Po prostu idzie.
To się nigdy nie zdarzy, gdy funkcja przechowywana w zmiennej środowiskowej zostanie wykonana zgodnie z prawem, przy pomocy export -f
. Ale po co być legalnym? Atakujący może po prostu wymyślić dowolną starą zmienną środowiskową, a jeśli będzie ona wyglądać jak funkcja, nowe powłoki bash to uznają!
Tak więc w naszym pierwszym przykładzie:
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
env
Komenda uruchamia polecenie z danej zmiennej zestawu. W tym przypadku ustawiamy x
coś, co wygląda jak funkcja. Ta funkcja jest tylko pojedynczą :
, która w rzeczywistości jest prostym poleceniem, które definiuje się jako brak działania. Ale potem, po tym, semi-colon
co sygnalizuje koniec definicji funkcji, pojawia się echo
polecenie. Nie powinno tak być, ale nic nas nie powstrzyma.
Następnie polecenie, które należy uruchomić w tym nowym środowisku, to nowa powłoka bash, ponownie z poleceniem „ echo this is a test
” lub „nic nie rób :
”, po czym zakończy działanie całkowicie nieszkodliwie.
Ale - ups! Kiedy ta nowa powłoka uruchamia się i odczytuje środowisko, dostaje się do x
zmiennej, a ponieważ wygląda jak funkcja, ocenia ją. Definicja funkcji jest ładowana nieszkodliwie - a następnie uruchamiana jest również nasza złośliwa funkcja. Tak więc, jeśli uruchomisz powyższe w systemie podatnym na ataki, zostaniesz z “OOPS”
powrotem wydrukowany. Lub atakujący może zrobić o wiele gorzej niż tylko drukować.
env
nie jest to konieczne. Można uzyskać ten sam rezultat (pass / fail w zależności od tego, czy Bash został zaktualizowany) za pomocą polecenia bez niego: x='() { :;}; echo OOPS' bash -c "echo this is a test"
. Wynika to z faktu, że poprzedzenie polecenia przypisaniem zmiennej przekazuje tę zmienną i jej wartość do środowiska polecenia ( bash -c "..."
w tym przypadku).
env
jest to konieczne, zależy od powłoki, z której uruchamiany jest test, a nie od powłoki testowanej. (Mogą być takie same. Nawet wtedy testujemy, w jaki sposób bash przetwarza własne środowisko.) Powłoki w stylu Bourne'a akceptują NAME=value command
składnię; Powłoki w stylu C (np. csh
, tcsh
) Nie. Test jest więc nieco bardziej przenośny env
(kosztem czasami powodując zamieszanie na temat jego działania).
W wersji niepakowanejbash
przechowuje wyeksportowane definicje funkcji jako zmienne środowiskowe.
Zapisz funkcję x
jako,
$ x() { bar; }
$ export -f x
I sprawdź jego definicję jako:
$ env | grep -A1 x
x=() { bar
}
Można to wykorzystać, definiując własne zmienne środowiskowe i interpretując je jako definicje funkcji. Na przykład env x='() { :;}'
byłoby traktowane jako
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Z man env
,
env
- uruchomić program w zmodyfikowanym środowisku.
:
nie rób nic poza wyjściem ze statusem wyjścia 0
. zobacz więcej
Po uruchomieniu nowej instancji niezakończonego basha jako bash -c "echo this is a test"
, spreparowana zmienna środowiskowa jest traktowana jako funkcja i ładowana. Odpowiednio otrzymuje się wynik
wrażliwy to jest test
Uwaga: Echo poza definicją funkcji zostało nieoczekiwanie wykonane podczas uruchamiania bash. Definicja funkcji jest tylko krokiem do przeprowadzenia oceny i wykorzystania, sama definicja funkcji i zmienna środowiskowa są dowolne. Powłoka patrzy na zmienne środowiskowe, widzi x, który wygląda tak, jakby spełniał ograniczenia, które wie o tym, jak wygląda definicja funkcji, i ocenia linię, mimowolnie również wykonując echo (może to być dowolne polecenie, złośliwe lub nie) . Zobacz także w tym
env test='() { echo "anything"; }' bash -c "echo otherthing"
, zobaczysz na wyjściu otherthing
. Zostało to poprawione w łatce. nie krępuj się, jeśli nadal nie jestem pewien.
unpatched bash
można wywoływać funkcję taką, jaka jest zdefiniowana, ale w poprawce bash
nie ma samej definicji.
echo vulnerable
) nie jest wykonywany. Zauważ, że w najnowszych łatach przekazana funkcja musi mieć określony prefiks ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
). %%
Zamiast pierwszych można użyć niektórych nowszych łatek ()
.