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 echotutaj 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 somecommandrobi 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"
envKomenda uruchamia polecenie z danej zmiennej zestawu. W tym przypadku ustawiamy xcoś, 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-colonco sygnalizuje koniec definicji funkcji, pojawia się echopolecenie. 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 xzmiennej, 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ć.
envnie 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).
envjest 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 commandskł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ę xjako,
$ 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 bashmożna wywoływać funkcję taką, jaka jest zdefiniowana, ale w poprawce bashnie 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 ().