Jak skutecznie wykrywać podatności w obrazach dockerowych?

15 Listopada 2021

W 2019 roku badacze z Palo Alto Unit 42 wykryli, że na ponad 2000 maszyn został uruchomiony pewien specyficzny obraz dockerowy. Wydawałoby się, że to tylko zwykły Centos jakich wiele na Docker Hubie. Miał on jednak w sobie coś wyjątkowego: w tle wykopywał kryptowalutę Monero. Bynajmniej nie dla właścicieli maszyn gdzie był on uruchomiony. Przestępcy sprytnie opakowali  w obraz Dockera wszystkie skrypty używane do minera i umieścili to w publicznym repozytorium. Niczego nieświadomi użytkownicy pobrali go przynajmniej 10 000 razy.

Ponad połowa obrazów dockerowych dostępnych na Docker Hub ma wykryte podatności lub zawiera malware. Jaką możemy mieć pewność, że pobrany nowy obraz nie jest szkodliwy dla organizacji? Jak wykryć niebezpieczną sytuację i ugasić pożar w zarodku? Tego dowiesz się już za moment, ale najpierw przyjrzyjmy się bliżej owym zagrożeniom.

 

Docker bardzo wygodny, ale czy bezpieczny?

Różne repozytoria na Docker Hub

Docker Hub to publiczne repozytorium obrazów dockerowych. Miliony obiektów, różnych wersji aplikacji czy dystrybucji dostępne dla każdego. Można tam znaleźć 3 rodzaje obrazów. Oficjalnegenerowane i publikowane bezpośrednio przez firmę Docker. Można znaleźć pośród nich najpopularniejsze dystrybucje Linuksa (Ubuntu, Debian, Alpine) i popularne aplikacje (Nginx, Postgres, Traefik i wiele innych). Drugi rodzaj to obrazy od Zweryfikowanych dostawców, czyli dostarczone przez zaufane firmy, zwykle dostawców konkretnego oprogramowania (np. Oracle, Elastic czy IBM). Ostatnią grupą obrazów są te dostarczone za pomocą prywatnych kont użytkowników. Dotyczą one zwykle rzadziej używanych aplikacji czy systemów. Pobierając taki obraz należy zwrócić szczególną ostrożność:

  • przeanalizować udostępniony Dockerfile
  • zweryfikować dostawcę oprogramowania
  • zwrócić uwagę na popularność obrazu — wybierać raczej te, które były pobrane miliony razy.

Instrukcje uruchomienia obrazu

Kolejnym źródłem zagrożenia jest instrukcja użycia publikowana na stronie konkretnego obrazu. Taka instrukcja jest zwykle pomocna gdy nie znamy oprogramowania i uruchamiamy je po raz pierwszy. Sprowadza się to zwykle do wywołania polecenia docker run z konkretnymi parametrami. Owe parametry mogą sprowadzać niebezpieczeństwo na nasz system. Uruchamianie kontenera w trybie uprzywilejowanym (–privileged), dodawanie capabilities (–cap-add) lub montowanie katalogów systemowych (-v /var, /etc, /usr) może zaburzyć separację pomiędzy systemem bazowym a kontenerem. Z uwagi na to, że daemon dockera uruchamiany jest zwykle z uprawnieniami administratora, procesy kontenera uzyskują niemal nieograniczony dostęp do maszyny hosta. Może to doprowadzić do uszkodzenia/zainfekowania systemu lub wycieku wrażliwych informacji.

Jak przestrzec się przed takim zagrożeniem? Tak jak w poprzednim przypadku warto przede wszystkim zweryfikować dostawcę oprogramowania. Innym rozwiązaniem jest uruchamianie obrazu w środowisku izolowanym, takim jak maszyna wirtualna, i manualna weryfikacja jego działania.

Podatności aplikacji

Trzecim źródłem zagrożeń są podatności w aplikacjach umieszczonych w obrazie. Aplikacje takie jak np. Kibana bazują zwykle na innym obrazie z popularną dystrybucją Linuxa (często Debian lub Alpine). W związku z tym w takim obrazie znajduje się nie tylko interesująca nas aplikacja, ale też szereg różnych bibliotek i binariów. Często nie są one nawet związane z używaną aplikacją. Mogą natomiast zawierać błędy, które pozwalają na eskalację uprawnień do roota lub wywołanie krytycznego błędu w kontenerze. Tego typu błędy nazywamy podatnościami.

Jednym z rozwiązań tego problemu jest używanie obrazów tzw. distroless. Obrazy takie nie zawierają managerów pakietów, shella i wielu podstawowych programów, których zwykle spodziewamy się w Linuksie. Dzięki temu znacząco ograniczamy ilość binariów, dla których mogą istnieć podatności. Niestety użycie tego typu obrazów nie zawsze jest możliwe z uwagi na charakter aplikacji. W takim przypadku warto zastosować jeden z istniejących skanerów wykrywających podatności.

 

Czego użyć do wykrywania podatności?

Na rynku istnieje wiele narzędzi do wyszukiwania podatności. Wszystkie korzystają z publicznych baz jak nvd.nist.gov. Używają różnych podzestawów takich baz stąd różnią się ilością zgłaszanych błędów. Zestawienie znalezionych podatności dla popularnych obrazów prezentuje poniższa grafika.

Źródło: https://www.a10o.net/devsecops/docker-image-security-static-analysis-tool-comparison-anchore-engine-vs-clair-vs-trivy/

Clair

Najpopularniejszy otwartoźródłowy skaner podatności. Na GitHubie Działa w architekturze klient — serwer co powoduje pewną uciążliwość w potokach ciągłej integracji. Użycie wymaga też przejście złożonego procesu instalacji. Istnieją rozwiązania, które nieco upraszczają proces instalacji i usprawniają użycie w CI takie jak clair-local-scan. Wymaga jednak pamiętania o ciągłej aktualizacji bazy danych, która dostarczana jest w niezależnym obrazie.

Anchore/Grype

Jest to otwartoźródłowe narzędzie firmy Anchore. Jego cechą szczególną jest możliwość skanowania wszystkich pośrednich warstw obrazu. Grype rozpakowuje obraz, rozkłada go na czynniki pierwsze i wskazuje wszystkie znane podatności dla znalezionych aplikacji. Na GitHubie Grype otrzymał 809 gwiazdek. Listing z uruchomienia przedstawiono na poniższej animacji.

Docker scan

Docker także udostępnia swój mechanizm do wykrywania podatności. Niestety jest to usługa płatna, tylko dla zarejestrowanych użytkowników.

Trivy

Oprogramowanie rozwijane jest przez firmę Aquasec. Na GitHubie zdobył 8.6k gwiazdek. Aplikacja może działać samodzielnie lub w trybie klient — serwer. Trivy skanuje nie tylko zainstalowane paczki w kontenerze, ale także zależności wytwarzanych aplikacji. Dzięki temu możemy sprawdzić, czy używane w projektach zależności nie posiadają luk bezpieczeństwa. Dotyczy to managerów zależności takich jak Bundler, Composer, npm, yarn itp.

Trivy potrafi też analizować pliki konfiguracyjne Dockerfile, Kubernetes i Terraform. To prawdziwy szwajcarski scyzoryk wśród narzędzi do badania podatności. Aplikacja wykrywa podobną ilość błędów jak Clair, a jednocześnie jest łatwa w konfiguracji. Sprawia to, że jest chętnie używane w środowiskach ciągłej integracji. Przykładowe uruchomienie można obejrzeć na poniższej animacji.

Na podstawie powyższego najlepszym narzędziem wydaje się Trivy. W kolejnym rozdziale dowiesz się jak wdrożyć to do swojego potoku ciągłej integracji z użyciem Jenkinsa.

 

Jak dodać Trivy do potoku ciągłej integracji?

Trivy możemy używać na kilka sposobów. Autorzy udostępniają możliwość instalacji przy pomocy managera pakietów, z użyciem skryptu instalacyjnego lub używając wersji w kontenerze dockerowym. W przypadku potoków CI/CD ta ostatnia opcja jest najbardziej pożądana.
Aby użyć Trivy w Jenkinsie wystarczy zainstalować wtyczkę „Warnings next generation„, która zawiera parsery dla raportów wielu narzędzi do statycznej analizy. W naszym przypadku skupimy się na 2 funkcjonalnościach tego narzędzia:

  • badanie konfiguracji Dockerfile
  • badanie podatności w obrazie zbudowanym na bazie Dockerfile

Badanie konfiguracji pozwoli na sprawdzenie czy Dockerfile jest przygotowany zgodnie z dobrymi praktykami. W takim przypadku sprawdzane jest np. czy został użyty użytkownik inny niż root, czy nie używamy tagu 'latest’, czy nie są wyeksponowane niebezpieczne porty itp. Z kolei badanie podatności pozwoli nam na weryfikację wszystkich zainstalowanych w obrazie paczek i ich wersji. Dzięki temu możliwe będzie sprawdzenie, czy dla danej wersji nie został upubliczniony krytyczny błąd.

Poniżej znajduje się przykładowy kod, który realizuje opisaną funkcjonalność. Po zbudowaniu obrazu sprawdzany jest on z użyciem Trivy (trivy image …). W wyniku tego procesu wygenerowany zostanie raport json. Owy raport parsowany jest przez jenkinsa z użyciem polecenia recordIssues.

Weryfikacja Dockerfile odbywa się za pomocą 'trivy config …’. To polecenie również potrafi wygenerować raport w formacie json. Niestety parser jenkinsowy nie jest przystosowany do tego typu raportów. Miejmy nadzieję, że taka funkcjonalność wkrótce zostanie dodana. Na ten moment jeśli Dockerfile będzie zawierał dowolny błąd, potok zakończy się niepowodzeniem. Listing z uruchomienia prezentuje poniższa grafika.

 

Podsumowanie

Rozpowszechnienie stosowania kontenerów sprawiło, że interesują się nimi także cyberprzestępcy. Każdego dnia aktualizujemy mnóstwo paczek systemowych. Aktualizacja niesie za sobą ryzyko wprowadzenia nowej podatności do systemu. Zgodnie z duchem DevSecOps warto stosować systemy, które automatycznie wykrywają podatności już na wczesnym etapie developmentu. Pozwala to na szybsze rozwiązanie problemów i ogranicza ryzyko dla całej organizacji.

Opublikowane przez: Piotr Mierzwiński

Inne artykuły_