Zostaje opublikowana krytyczna podatność, biuletyn się rozchodzi i w ciągu godziny ktoś pyta na firmowym czacie: czy to nas dotyczy? Log4Shell rozsławił to pytanie. CVE-2021-44228 dotyczyło Log4j Core od wersji 2.0-beta9 do 2.15.0, biblioteki leżącej kilka poziomów głęboko w drzewie zależności niezliczonych produktów Java, i większość zespołów musiała w bolesny sposób ustalać, gdzie się znajduje.
Pytanie brzmi prosto. W rzeczywistości to trzy pytania:
- Czy podatny komponent jest w czymkolwiek, co budujemy lub dostarczamy?
- Jeśli tak, czy można go wykorzystać w naszym produkcie?
- Od kiedy i w których wydaniach?
Większość procesów odpowiada na dwa pierwsze. Trzecie to to, o które klienci, audytorzy i regulatorzy pytają w następnej kolejności, i najtrudniej na nie odpowiedzieć po fakcie.
Krok 1: Ustalić, czy komponent tam jest
Firmy dochodzą do odpowiedzi zwykle na jeden z czterech sposobów, mniej więcej w kolejności dojrzałości.
Popytać i poszukać. Ktoś pisze na Slacku, inżynierowie przeszukują repozytoria i lockfile pod kątem nazwy pakietu, a arkusz kalkulacyjny zbiera odpowiedzi. To wciąż najpopularniejsza metoda. Jest powolna, zależy od tego, kto odpowie, i pomija wszystko, co nie jest zadeklarowane w pliku: zależności zależności, biblioteki dołączone do kodu, obrazy bazowe, narzędzia instalowane podczas buildu.
Sprawdzić pulpity skanerów. Skanery zależności oznaczają CVE dla każdego repozytorium w ciągu kilku godzin. To szybsze, ale skaner raportuje o kodzie, który ma dziś przed sobą, zwykle o gałęzi domyślnej. Nie powie, które wydania mają Państwa klienci ani co faktycznie pobrał build sprzed trzech miesięcy.
Odpytać inwentarz SBOM. Zespoły, które prowadzą zestawienie komponentów oprogramowania dla każdego wydania, mogą zadać jedno pytanie o wszystkie naraz: które produkty i wersje zawierają dotknięte wersje tego pakietu? To pierwsza metoda, która daje odpowiedź o dostarczonym oprogramowaniu, a nie tylko o tym w repozytorium.
Dopasowywać na bieżąco. Gdy SBOM-y są monitorowane względem danych o podatnościach, lista dotkniętych produktów istnieje, zanim ktokolwiek zapyta. Wątek na czacie zaczyna się od odpowiedzi, a nie od pytania.
Jakość każdej metody zależy od tego, co faktycznie zawiera inwentarz. Typowe martwe pola to:
- Zależności przechodnie. Podatny pakiet rzadko jest tym, który dodali Państwo sami. Pojawia się trzy lub cztery poziomy niżej.
- Wszystko, czego nie deklaruje manifest. Pakiety instalowane przez skrypty buildu, narzędzia
npx, kroki Dockerfile, przywrócone cache oraz dołączony kod C i C++. - Stare wydania. Gałęzi, która już się nie buduje, nie da się ponownie przeskanować, ale produkt z niej zbudowany może nadal działać u klientów.
Krok 2: Zdecydować, czy to ma znaczenie
Komponent może być obecny, nie stanowiąc realnego ryzyka, dlatego kolejnym krokiem jest triage:
- Wersja i konfiguracja. Czy wersja dokładnie mieści się w dotkniętym zakresie? Czy podatna funkcja jest wkompilowana i włączona?
- Osiągalność. Czy Państwa kod w ogóle wywołuje podatną funkcję?
- Ekspozycja. Czy komponent jest osiągalny z sieci lub z niezaufanych danych wejściowych, czy używany tylko w czasie buildu?
- Środki łagodzące. Czy istnieje sandboxing, ograniczenie sieciowe lub konfiguracja, która blokuje exploit?
- Sygnały wykorzystania. CVSS podaje wagę, EPSS szacuje prawdopodobieństwo wykorzystania CVE w ciągu najbliższych 30 dni, a katalog Known Exploited Vulnerabilities agencji CISA wymienia podatności już wykorzystywane w praktyce. Razem decydują o tym, czym zająć się najpierw.
Krok 3: Zapisać decyzję
Wynik zapisuje się dla każdego produktu i wersji, coraz częściej jako oświadczenie VEX (Vulnerability Exploitability eXchange). Minimalne wymagania CISA dla VEX definiują cztery statusy: not affected, affected, fixed i under investigation. Oświadczenie „not affected” musi podawać przyczynę, na przykład to, że podatnego kodu nie ma lub że atakujący nie może do niego dotrzeć.
Ten zapis zasila wszystko, co następuje później: poprawkę i zawierające ją wydania, biuletyn bezpieczeństwa dla klientów oraz każdy raport, jakiego oczekuje regulator. Zgodnie z unijnym Cyber Resilience Act producent musi na przykład wysłać wczesne ostrzeżenie o aktywnie wykorzystywanej podatności w swoim produkcie w ciągu 24 godzin od uzyskania o niej wiedzy.
Krok 4: Ustalić okno ekspozycji
Pytanie „czy to nas dotyczy?” ma drugą część, którą często się pomija: jak długo nas dotyczyło?
Podatność istniała na długo przed publikacją CVE. Log4Shell był w Log4j od wersji 2.0-beta9, wydanej wiele lat przed ujawnieniem błędu. Państwa ekspozycja zaczęła się w dniu, w którym build po raz pierwszy pobrał podatną wersję, a skończyła w dniu, w którym zastąpiono ostatni zawierający ją build. To okno jest potrzebne, aby:
- powiedzieć klientom, których z używanych przez nich wydań sprawa dotyczy, a nie tylko najnowszego
- zawęzić dochodzenie po incydencie do właściwego okresu, jeśli podatność mogła zostać wykorzystana
- pokazać audytorowi lub regulatorowi, kiedy problem trafił do produktu i kiedy dostarczono poprawkę
Skanowanie dzisiejszego kodu tego nie zapewni. Bieżący lockfile mówi, czego repozytorium chce teraz, a nie co zainstalował każdy wcześniejszy build. Jedynym wiarygodnym źródłem jest zapis każdego buildu, wykonany w trakcie jego działania i później zachowany.
Jak odpowiada na to CRACI
CRACI uruchamia Państwa zadania GitHub Actions na własnych runnerach i rejestruje każdy pakiet, który każdy build faktycznie pobiera, bezpośredni i przechodni, łącznie z pakietami instalowanymi przez skrypty i przywróconymi z cache. SBOM każdego buildu jest zachowywany, więc historia już istnieje, gdy CVE zostaje opublikowane.
Gdy pojawia się nowe CVE, odpowiedź jest już gotowa: każdy wcześniejszy build i jego SBOM, informacja, które z nich zawierały podatną zależność, bezpośrednią lub przechodnią, oraz okres, w którym Państwa to dotyczyło. Bez arkuszy, bez ponownego skanowania, bez odtwarzania z lockfile. Pierwszy build, który ją zawierał, i build, który ją usunął, wyznaczają okno ekspozycji, tak daleko wstecz, jak sięga okres przechowywania (domyślnie 180 dni, niestandardowy okres w planie Enterprise).
Gdy już wiadomo, bramka polityki może blokować buildy zawierające to CVE, aby późniejsza aktualizacja zależności lub przywrócony cache nie mogły po cichu wprowadzić podatnej wersji z powrotem do wydania.
Od tego momentu reszta procesu ma na czym się oprzeć:
- CRACI monitoruje SBOM-y na bieżąco, więc nowe CVE są dopasowywane do Państwa buildów i nikt nie musi o to pytać.
- Zespoły bezpieczeństwa wykonują triage znalezisk i przekazują je zespołom odpowiedzialnym za poprawkę, a CRACI obsługuje VEX do zapisu wyniku.
- Inwentarz CRACI pokazuje, które wersje oprogramowania są wdrożone w których produktach.
- Na potrzeby CRA CRACI składa w Państwa imieniu wczesne ostrzeżenie, powiadomienie i raport końcowy.
Prosimy umówić demo, aby zobaczyć historię buildów jednego z Państwa repozytoriów.
