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?
bash
shellshock
heemayl
źródło
źródło
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ć:
Spowoduje to wydrukowanie „OOPS” w systemie podatnym na zagrożenia, ale zamknie się cicho, jeśli poprawiono bash.
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:
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ę!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: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:
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
Komenda uruchamia polecenie z danej zmiennej zestawu. W tym przypadku ustawiamyx
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ć.źródło
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śnyenv
(kosztem czasami powodując zamieszanie na temat jego działania).W wersji niepakowanej
bash
przechowuje wyeksportowane definicje funkcji jako zmienne środowiskowe.Zapisz funkcję
x
jako,I sprawdź jego definicję jako:
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 jakoDo czego służy polecenie sprawdzania shellshocka,
Z
man env
,env
- uruchomić program w zmodyfikowanym środowisku.:
nie rób nic poza wyjściem ze statusem wyjścia0
. zobacz więcejPo 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źródło
env test='() { echo "anything"; }' bash -c "echo otherthing"
, zobaczysz na wyjściuotherthing
. 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 poprawcebash
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()
.