TL; DR
Luka w shellshock jest całkowicie naprawiona
- W gałęzi bash-2.05b: 2.05b.10 i nowsze (wraz z łatką 10)
- W gałęzi bash-3.0: 3.0.19 i nowsze (wraz z łatką 19)
- W gałęzi bash-3.1: 3.1.20 i nowsze (wraz z łatką 20)
- W gałęzi bash-3.2: 3.2.54 i nowsze (wraz z łatką 54)
- W gałęzi bash-4.0: 4.0.41 i nowsze (łatka 41 w zestawie)
- W gałęzi bash-4.1: 4.1.14 i nowsze (wraz z łatką 14)
- W gałęzi bash-4.2: 4.2.50 i nowsze (wraz z łatką 50)
- W gałęzi bash-4.3: 4.3.27 i nowsze (wraz z łatką 27)
Jeśli twoja wersja bash pokazuje starszą wersję, twój dostawca systemu operacyjnego mógł ją załatać sam, więc najlepiej to sprawdzić.
Jeśli:
env xx='() { echo vulnerable; }' bash -c xx
pokazuje „wrażliwy”, wciąż jesteś wrażliwy. Jest to jedyny istotny test (czy parser bash jest nadal narażony na kod w dowolnej zmiennej środowiskowej).
Detale.
Błąd był w początkowej realizacji funkcji export / import wprowadzony na 5 th sierpnia 1989 roku przez Briana Foxa, a po raz pierwszy wydany w bash-1.03 około miesiąc później w czasie, gdy bash nie był w takim powszechnym użyciu, zanim bezpieczeństwo było tyle obaw, że HTTP i sieć, a nawet Linux istniały.
Z ChangeLog w 1.05 :
Fri Sep 1 18:52:08 1989 Brian Fox (bfox at aurel)
* readline.c: rl_insert (). Optimized for large amounts
of typeahead. Insert all insertable characters at once.
* I update this too irregularly.
Released 1.03.
[...]
Sat Aug 5 08:32:05 1989 Brian Fox (bfox at aurel)
* variables.c: make_var_array (), initialize_shell_variables ()
Added exporting of functions.
Niektóre dyskusje w gnu.bash.bug i comp.unix.questions w tym czasie również wspominają o tej funkcji.
Łatwo zrozumieć, jak się tam dostało.
bash eksportuje funkcje w zmiennych env, takich jak
foo=() {
code
}
A przy imporcie wszystko, co musi zrobić, to zinterpretować to z =
zastąpionym spacją ... z wyjątkiem tego, że nie powinna ślepo interpretować.
Jest to również podzielone w tym, że w bash
(w przeciwieństwie do powłoki Bourne'a) zmienne skalarne i funkcje mają inną przestrzeń nazw. Właściwie jeśli masz
foo() { echo bar; }; export -f foo
export foo=bar
bash
z przyjemnością umieści oba te elementy w środowisku (tak wpisy o tej samej nazwie), ale wiele narzędzi (w tym wiele powłok) ich nie propaguje.
Można by również argumentować, że bash powinien używać do tego BASH_
prefiksu przestrzeni nazw, ponieważ jest to zmienne env istotne tylko od bash do bash. rc
używa fn_
przedrostka dla podobnej funkcji.
Lepszym sposobem na jego wdrożenie byłoby umieszczenie definicji wszystkich eksportowanych zmiennych w zmiennej takiej jak:
BASH_FUNCDEFS='f1() { echo foo;}
f2() { echo bar;}...'
Które nadal będą musiały być oczyszczone, ale przynajmniej, że nie może być więcej niż wykorzystywaną $BASH_ENV
lub $SHELLOPTS
...
Jest tam łatka, która uniemożliwia bash
interpretowanie czegokolwiek innego niż definicja funkcji w niej zawarta ( https://lists.gnu.org/archive/html/bug-bash/2014-09/msg00081.html ), i to ta, która ma zostały zastosowane we wszystkich aktualizacjach bezpieczeństwa z różnych dystrybucji Linuksa.
Jednak bash nadal interpretuje tam znajdujący się kod i każdy błąd w interpretatorze może zostać wykorzystany. Jeden taki błąd został już znaleziony (CVE-2014-7169), chociaż jego wpływ jest znacznie mniejszy. Wkrótce pojawi się kolejna łatka.
Aż do poprawki hartowania, która uniemożliwia bashowi interpretację kodu w dowolnej zmiennej (np. Przy użyciu BASH_FUNCDEFS
powyższego podejścia), nie będziemy pewni, czy nie będziemy podatni na błąd w parserze bash. I wierzę, że prędzej czy później pojawi się taka poprawka hartująca.
Edytuj 28.09.2014
Znaleziono dwa dodatkowe błędy w parserze (CVE-2014-718 {6,7}) (zauważ, że większość pocisków musi zawierać błędy w parserze dla przypadków narożnych, co nie byłoby problemem, gdyby ten parser nie zostały narażone na niezaufane dane).
Podczas gdy wszystkie 3 błędy 7169, 7186 i 7187 zostały naprawione w kolejnych łatkach, Red Hat naciskał na poprawkę hartowania. W swojej łatce zmienili zachowanie, tak że funkcje zostały wyeksportowane do zmiennych zwanych BASH_FUNC_myfunc()
mniej lub bardziej wyprzedzającymi decyzję projektową Cheta.
Później Chet opublikował tę poprawkę jako oficjalną łatkę upstreams .
Ta łatka utwardzająca lub jej warianty są teraz dostępne dla większości głównych dystrybucji Linuksa i ostatecznie trafiły do Apple OS / X.
To teraz niepokoi wszelkie arbitralne zmienne env wykorzystujące parser za pośrednictwem tego wektora, w tym dwie inne luki w parserze (CVE-2014-627 {7,8}), które zostały ujawnione później przez Michała Zalewskiego (CVE-2014-6278 jest prawie tak źle jak CVE-2014-6271) na szczęście po tym, jak większość ludzi zdążyła zainstalować łatkę hartującą
Błędy w parserze również zostaną naprawione, ale nie stanowią już tak dużego problemu, ponieważ parser nie jest już tak łatwo narażony na niezaufane dane wejściowe.
Pamiętaj, że chociaż luka w zabezpieczeniach została naprawiona, prawdopodobnie zobaczymy pewne zmiany w tym obszarze. Początkowy fix dla CVE-2014-6271 złamał kompatybilności wstecznej w tym, że zatrzymuje funkcje importowania z .
lub :
lub /
w ich imieniu. Nadal można je zadeklarować przez bash, co powoduje niespójne zachowanie. Ponieważ funkcje z .
i :
w ich imieniu są powszechnie używane, to prawdopodobnie poprawka przywraca przyjmowanie przynajmniej tych z otoczenia.
Dlaczego nie znaleziono go wcześniej?
Zastanawiałem się nad tym. Mogę podać kilka wyjaśnień.
Po pierwsze, myślę, że gdyby badacz bezpieczeństwa (a nie jestem zawodowym badaczem bezpieczeństwa) specjalnie szukał luk w bash, prawdopodobnie by go znalazł.
Na przykład, gdybym był badaczem bezpieczeństwa, moje podejście mogłoby wyglądać następująco:
- Sprawdź, skąd
bash
pobiera dane wejściowe i co z nimi robi. A środowisko jest oczywiste.
- Sprawdź, w których miejscach
bash
wywoływany jest tłumacz i na jakie dane. Znów będzie się wyróżniał.
- Importowanie eksportowanych funkcji jest jedną z funkcji, które są wyłączone, gdy
bash
jest ustawiony na setuid / setgid, co czyni go jeszcze bardziej oczywistym miejscem do patrzenia.
Teraz podejrzewam, że nikt nie pomyślał o traktowaniu bash
(tłumacza) jako zagrożenia, ani że zagrożenie mogło przyjść w ten sposób.
bash
Interpreter nie jest przeznaczona do przetwarzania wejściowych niezaufane.
Skrypty powłoki (nie interpreter) są często analizowane z punktu widzenia bezpieczeństwa. Składnia powłoki jest tak niewygodna i istnieje wiele ostrzeżeń dotyczących pisania wiarygodnych skryptów (widziałeś mnie lub innych, którzy wspominają o operatorze split + glob lub dlaczego na przykład powinieneś cytować zmienne?), Że dość często można znaleźć luki w zabezpieczeniach w skryptach, które przetwarzają niezaufane dane.
Dlatego często słyszysz, że nie powinieneś pisać skryptów powłoki CGI, lub skrypty setuid są wyłączone w większości Uniksów. Lub też powinieneś zachować szczególną ostrożność podczas przetwarzania plików w katalogach do zapisu na świecie (patrz na przykład CVE-2011-0441 ).
Skupiamy się na tym, na skryptach powłoki, a nie na tłumaczu.
Można wystawiać interpreter powłoki do niezaufanych danych (karmienie danych zagranicznych jako Shellcode interpretacji) przez eval
lub .
lub nazywając ją pod warunkiem użytkowników plików, ale wtedy nie trzeba lukę w zabezpieczeniach bash
, żeby go wykorzystać. To całkiem oczywiste, że jeśli przekazujesz niezarządzane dane do powłoki do interpretacji, to ją zinterpretuje.
Powłoka jest więc wywoływana w zaufanych kontekstach. Dostaje stałe skrypty do interpretacji i częściej (ponieważ tak trudno jest pisać wiarygodne skrypty) stałe dane do przetworzenia.
Na przykład w kontekście sieciowym można wywołać powłokę w czegoś takiego jak:
popen("sendmail -oi -t", "w");
Co może pójść nie tak? Jeśli przewiduje się coś złego, dotyczy to danych podawanych do tego sendmaila, a nie tego, w jaki sposób przetwarzany jest sam wiersz poleceń powłoki lub jakie dodatkowe dane są podawane do tej powłoki. Nie ma powodu, dla którego chciałbyś wziąć pod uwagę zmienne środowiskowe przekazywane do tej powłoki. A jeśli to zrobisz, zdasz sobie sprawę, że to są wszystkie zmienne env, których nazwa zaczyna się od „HTTP_” lub są dobrze znanymi zmiennymi env CGI, takimi jak SERVER_PROTOCOL
lub QUERYSTRING
z którymi żadna powłoka lub sendmail nie mają nic wspólnego.
W kontekstach podniesienia uprawnień, takich jak uruchamianie setuid / setgid lub przez sudo, środowisko jest ogólnie brane pod uwagę i w przeszłości występowało wiele luk, ponownie nie przeciwko samej powłoce, ale przeciwko rzeczom, które podnoszą przywileje, takie jak sudo
(patrz na przykład CVE -2011-3628 ).
Na przykład bash
nie ufa środowisku, gdy jest setuid lub wywoływane przez polecenie setuid (pomyśl mount
na przykład, że wywołuje pomocników). W szczególności ignoruje eksportowane funkcje.
sudo
robi czyszczenia środowiska: wszystkie domyślnie wyjątkiem białej listy, a jeśli jest skonfigurowana, aby nie, przynajmniej czarnych listach kilka, które są znane wpływa na powłokę lub innej osoby (jak PS4
, BASH_ENV
, SHELLOPTS
...). Umieszcza również na czarnej liście zmienne środowiskowe, których treść zaczyna się ()
(dlatego CVE-2014-6271 nie pozwala na eskalację uprawnień przez sudo
).
Ale znowu, dotyczy to kontekstów, w których środowisku nie można ufać: w tym kontekście złośliwy użytkownik może ustawić dowolną zmienną o dowolnej nazwie i wartości. Nie dotyczy to serwerów WWW / ssh ani wszystkich wektorów wykorzystujących CVE-2014-6271, w których środowisko jest kontrolowane (przynajmniej nazwa zmiennych środowiskowych jest kontrolowana ...)
Ważne jest, aby zablokować zmienną taką echo="() { evil; }"
, ale nie HTTP_FOO="() { evil; }"
, ponieważ HTTP_FOO
nie będzie wywoływana jako polecenie przez żaden skrypt powłoki lub wiersz poleceń. A apache2 nigdy nie ustawi echo
ani BASH_ENV
zmiennej.
To oczywiste, że niektóre zmienne środowiskowe powinny znajdować się na czarnej liście w niektórych kontekstach na podstawie ich nazwy , ale nikt nie pomyślał, że powinny być na czarnej liście na podstawie ich zawartości (z wyjątkiem sudo
). Innymi słowy, nikt nie pomyślał, że arbitralne zmienne środowiskowe mogą być wektorem do wstrzykiwania kodu.
Jeśli chodzi o to, czy rozległe testy po dodaniu tej funkcji mogły ją złapać, powiedziałbym, że jest mało prawdopodobne.
Podczas testowania funkcji testujesz funkcjonalność. Funkcjonalność działa dobrze. Jeśli wyeksportujesz funkcję w jednym bash
wywołaniu, zostanie ona zaimportowana w innym. Bardzo dokładne testowanie może wykryć problemy, gdy zarówno zmienna, jak i funkcja o tej samej nazwie są eksportowane lub gdy funkcja jest importowana w lokalizacji innej niż ta, w której została wyeksportowana.
Aby jednak wykryć lukę, nie jest to test funkcjonalności, który musiałbyś wykonać. Aspekt bezpieczeństwa musiałby być głównym celem i nie testowałbyś funkcjonalności, ale mechanizm i sposób, w jaki można by ją wykorzystać.
Nie jest to coś, co programiści (szczególnie w 1989 roku) często mają w głowie, a deweloperowi powłoki można usprawiedliwić, że jego oprogramowanie prawdopodobnie nie nadaje się do wykorzystania w sieci.