Zalecenia dotyczące zabezpieczania cyklu życia programowania

Dotyczy tego zalecenia dotyczącego listy kontrolnej zabezpieczeń platformy Azure Well-Architected Framework:

SE:02 Zachowaj bezpieczny cykl życia programowania przy użyciu wzmocnionego, głównie zautomatyzowanego i poddawanego inspekcji łańcucha dostaw oprogramowania. Uwzględnij bezpieczny projekt przy użyciu modelowania zagrożeń w celu ochrony przed implementacjami zwalczania zabezpieczeń.

Powiązany przewodnik: Analiza zagrożeń

W tym przewodniku opisano zalecenia dotyczące wzmacniania poziomu kodu, środowiska programistycznego i łańcucha dostaw oprogramowania przez zastosowanie najlepszych rozwiązań w zakresie zabezpieczeń w całym cyklu projektowania. Aby zrozumieć te wskazówki, musisz mieć wiedzę na temat metodyki DevSecOps.

Diagram cyklu zabezpieczeń.

Usługa DevSecOps integruje zabezpieczenia z procesami DevOps przez:

  • Automatyzowanie testowania i walidacji zabezpieczeń.

  • Implementowanie narzędzi, takich jak potoki zabezpieczeń, w celu skanowania kodu i infrastruktury jako kodu (IaC) pod kątem luk w zabezpieczeniach.

Podstawowym elementem obciążenia jest kod aplikacji, który implementuje logikę biznesową. Kod i proces tworzenia kodu muszą być wolne od wad zabezpieczeń , aby zapewnić poufność, integralność i dostępność.

Nie wystarczy zabezpieczyć tylko płaszczyznę infrastruktury przy użyciu kontrolek dotyczących tożsamości i sieci i innych miar. Zapobiegaj nieprawidłowej implementacji kodu lub naruszonego bloku kodu w celu wzmocnienia ogólnej postawy zabezpieczeń. Płaszczyzna użycia, czyli kod aplikacji, musi być również wzmocniony. Proces integrowania zabezpieczeń z cyklem życia programowania jest zasadniczo procesem wzmacniania zabezpieczeń. Podobnie jak wzmacnianie zabezpieczeń zasobów, zaostrzenie programowania kodu jest również niezależne od kontekstu. Celem jest zwiększenie zabezpieczeń, a nie wymagań funkcjonalnych aplikacji. Aby uzyskać informacje dotyczące wzmacniania zabezpieczeń, zobacz Zalecenia dotyczące wzmacniania zabezpieczeń zasobów.

Definicje

Okres Definicja
Security Development Lifecycle (SDL) Zestaw rozwiązań oferowanych przez firmę Microsoft, który obsługuje wymagania dotyczące zapewniania zabezpieczeń i zgodności.
Cykl życia tworzenia oprogramowania (SDLC) Wieloestowy, systematyczny proces tworzenia systemów oprogramowania.

Kluczowe strategie projektowania

Środki zabezpieczeń należy zintegrować w wielu punktach z istniejącym cyklem życia tworzenia oprogramowania (SDLC), aby zapewnić:

  • Wybory projektowe nie prowadzą do luk w zabezpieczeniach.

  • Kod aplikacji i konfiguracja nie tworzą luk w zabezpieczeniach z powodu implementacji możliwej do wykorzystania i nieprawidłowych praktyk kodowania.

  • Oprogramowanie pozyskane za pośrednictwem łańcucha dostaw nie wprowadza zagrożeń bezpieczeństwa.

  • Procesy tworzenia i wdrażania kodu aplikacji nie są modyfikowane.

  • Luki w zabezpieczeniach ujawnione za pośrednictwem zdarzeń są ograniczane.

  • Nieużywane zasoby są prawidłowo zlikwidowane.

  • Wymagania dotyczące zgodności nie są naruszone ani ograniczone.

  • Rejestrowanie inspekcji jest implementowane w środowiskach deweloperskich.

W poniższych sekcjach przedstawiono strategie zabezpieczeń dla często praktykowanych faz SDLC.

Faza wymagań

Celem fazy wymagań jest zebranie i przeanalizowanie funkcjonalnych i niefunkcjonalnych wymagań aplikacji lub nowej funkcji aplikacji. Ta faza jest ważna, ponieważ ułatwia tworzenie barier zabezpieczających dostosowanych do celów aplikacji. Ochrona danych i integralności aplikacji powinna być podstawowym wymaganiem w każdej fazie cyklu projektowania.

Rozważmy na przykład aplikację, która musi obsługiwać krytyczne przepływy użytkowników, które umożliwiają użytkownikowi przekazywanie i manipulowanie danymi. Opcje projektowania zabezpieczeń powinny obejmować gwarancje interakcji użytkownika z aplikacją, takie jak uwierzytelnianie i autoryzowanie tożsamości użytkownika, co pozwala na wykonywanie tylko dozwolonych akcji na danych i zapobieganie wstrzyknięciu kodu SQL. Podobnie obejmują wymagania niefunkcjonalne, takie jak dostępność, skalowalność i łatwość konserwacji. Opcje zabezpieczeń powinny obejmować granice segmentacji, ruch przychodzący i ruch wychodzący zapory oraz inne istotne zabezpieczenia.

Wszystkie te decyzje powinny prowadzić do dobrej definicji stanu zabezpieczeń aplikacji. Udokumentowanie wymagań dotyczących zabezpieczeń w uzgodnionej specyfikacji i odzwierciedlenie ich na liście prac. Powinien wyraźnie określać inwestycje w zabezpieczenia oraz kompromisy i zagrożenia, które firma chce podjąć, jeśli inwestycje nie są zatwierdzone przez zainteresowane strony biznesowe. Możesz na przykład udokumentować konieczność użycia zapory aplikacji internetowej (WAF) przed aplikacją, takiej jak usługa Azure Front Door lub Azure Application Gateway. Jeśli zainteresowane strony biznesowe nie są gotowe do zaakceptowania dodatkowych kosztów korzystania z zapory aplikacji internetowej, muszą zaakceptować ryzyko, że ataki warstwy aplikacji mogą być kierowane do aplikacji.

Zbieranie wymagań dotyczących zabezpieczeń jest krytyczną częścią tej fazy. Bez tego nakładu pracy fazy projektowania i implementacji będą oparte na niestatysowanych opcjach, co może prowadzić do luk w zabezpieczeniach. Może być konieczne późniejsze zmianę implementacji w celu dostosowania ich do zabezpieczeń, co może być kosztowne.

Faza projektowania

W tej fazie wymagania dotyczące zabezpieczeń są konwertowane na wymagania techniczne. W specyfikacji technicznej udokumentuj wszystkie decyzje projektowe, aby zapobiec niejednoznaczności podczas implementacji. Oto kilka typowych zadań:

Definiowanie wymiaru zabezpieczeń architektury systemu

Nakładaj architekturę za pomocą mechanizmów kontroli zabezpieczeń. Na przykład kontrolki, które są praktyczne w granicach izolacji na strategię segmentacji, typy tożsamości wymaganych dla składników aplikacji i typ metod szyfrowania do użycia. Aby zapoznać się z przykładowymi architekturami, zobacz ilustracje w sekcjach Przykładowe artykuły Zarządzanie tożsamościami i dostępem oraz Sieć .

Ocena zapewnianych przez platformę cen

Ważne jest, aby zrozumieć podział odpowiedzialności między Tobą a dostawcą usług w chmurze. Unikaj nakładania się na siebie na przykład natywnych mechanizmów kontroli zabezpieczeń platformy Azure. Uzyskasz lepsze pokrycie zabezpieczeń i będziesz w stanie ponownie przydzielić zasoby programistyczne do potrzeb aplikacji.

Jeśli na przykład projekt wywołuje zaporę aplikacji internetowej na wejściu, możesz odciążyć tę odpowiedzialność za moduł równoważenia obciążenia, taki jak Application Gateway lub Azure Front Door. Unikaj replikowania funkcji jako kodu niestandardowego w aplikacji.

Wybierz tylko zaufane struktury, biblioteki i oprogramowanie łańcucha dostaw. Projekt powinien również określać bezpieczną kontrolę wersji. Zależności aplikacji powinny być pozyskiwane od zaufanych firm. Dostawcy zewnętrzni powinni mieć możliwość spełnienia wymagań dotyczących zabezpieczeń i udostępnienia ich planu odpowiedzialnego ujawnienia. Wszelkie zdarzenia zabezpieczeń powinny być natychmiast zgłaszane, aby można było wykonać niezbędne działania. Ponadto niektóre biblioteki mogą być zabronione przez organizację. Na przykład oprogramowanie może być bezpieczne przed lukami w zabezpieczeniach, ale nadal niedozwolone z powodu ograniczeń licencjonowania.

Aby upewnić się, że te wskazówki są zgodne ze wszystkimi współautorami oprogramowania, zachowaj listę zatwierdzonych i/lub niezatwierdzonych struktur, bibliotek i dostawców. Jeśli to możliwe, umieść zabezpieczenia w potokach deweloperskich, aby obsługiwać listę. Jak najwięcej, automatyzuj używanie narzędzi do skanowania zależności pod kątem luk w zabezpieczeniach.

Określ wzorce projektowe zabezpieczeń, które należy zaimplementować w kodzie aplikacji.

Wzorce mogą obsługiwać problemy związane z zabezpieczeniami, takie jak segmentacja i izolacja, silna autoryzacja, jednolite zabezpieczenia aplikacji i nowoczesne protokoły. Niektóre wzorce operacyjne, takie jak wzorzec kwarantanny, mogą pomóc zweryfikować i zablokować użycie oprogramowania, które może potencjalnie wprowadzić luki w zabezpieczeniach.

Aby uzyskać więcej informacji, zobacz Wzorce projektowe w chmurze, które obsługują zabezpieczenia.

Bezpieczne przechowywanie wpisów tajnych aplikacji

Bezpiecznie zaimplementuj użycie wpisów tajnych aplikacji i wstępnie udostępnionych kluczy używanych przez aplikację. Poświadczenia i wpisy tajne aplikacji nigdy nie powinny być przechowywane w drzewie kodu źródłowego. Użyj zasobów zewnętrznych, takich jak Azure Key Vault, aby upewnić się, że jeśli kod źródłowy stanie się dostępny dla potencjalnego osoby atakującej, nie można uzyskać dalszego dostępu. Ogólnie rzecz biorąc, znajdź sposoby unikania wpisów tajnych. Użycie tożsamości zarządzanych, jeśli to możliwe, jest jednym ze sposobów osiągnięcia tego celu. Aby uzyskać więcej informacji, zobacz Zalecenia dotyczące zarządzania wpisami tajnymi aplikacji.

Definiowanie planów testów

Zdefiniuj jasne przypadki testowe pod kątem wymagań dotyczących zabezpieczeń. Oceń, czy te testy można zautomatyzować w potokach. Jeśli twój zespół ma procesy do testowania ręcznego, uwzględnij wymagania dotyczące zabezpieczeń dla tych testów.

Uwaga

Wykonaj modelowanie zagrożeń w tej fazie. Modelowanie zagrożeń może potwierdzić, że wybory projektowe są zgodne z wymaganiami dotyczącymi zabezpieczeń i uwidaczniają luki, które należy ograniczyć. Jeśli obciążenie obsługuje wysoce poufne dane, zainwestuj w ekspertów ds. zabezpieczeń, którzy mogą pomóc w prowadzeniu modelowania zagrożeń.

Wstępne ćwiczenie modelowania zagrożeń powinno nastąpić w fazie projektowania, gdy jest definiowana architektura oprogramowania i projekt wysokiego poziomu. Wykonanie tej czynności w tej fazie pomaga zidentyfikować potencjalne problemy z zabezpieczeniami przed włączeniem ich do struktury systemu. Jednak to ćwiczenie nie jest jednorazowym działaniem. Jest to ciągły proces, który powinien być kontynuowany w całej ewolucji oprogramowania.

Aby uzyskać więcej informacji, zobacz Zalecenia dotyczące analizy zagrożeń.

Faza programowania i testowania

W tej fazie celem jest zapobieganie wadom zabezpieczeń i manipulowaniu w kodzie, kompilacji i potokach wdrażania.

Dobrze wyszkolone w bezpiecznych praktykach dotyczących kodu

Zespół programistyczny powinien mieć formalne i wyspecjalizowane szkolenia w zakresie bezpiecznych praktyk kodowania. Na przykład deweloperzy internetu i interfejsu API mogą potrzebować konkretnego szkolenia w celu ochrony przed atakami skryptowymi między witrynami, a deweloperzy zaplecza mogą skorzystać z szczegółowego szkolenia, aby uniknąć ataków na poziomie bazy danych, takich jak ataki polegających na wstrzyknięciu kodu SQL.

Deweloperzy powinni być zobowiązani do ukończenia tego szkolenia, zanim będą mogli uzyskać dostęp do produkcyjnego kodu źródłowego.

Należy również wykonywać wewnętrzne przeglądy kodu równorzędnego w celu promowania ciągłego uczenia się.

Korzystanie z narzędzi do testowania zabezpieczeń

Wykonaj modelowanie zagrożeń, aby ocenić bezpieczeństwo architektury aplikacji.

Użyj statycznego testowania zabezpieczeń aplikacji (SAST), aby analizować kod pod kątem luk w zabezpieczeniach. Zintegruj tę metodologię ze środowiskiem deweloperów, aby wykrywać luki w zabezpieczeniach w czasie rzeczywistym.

Użyj dynamicznego testowania zabezpieczeń aplikacji (DAST) podczas wykonywania. Ten łańcuch narzędzi może sprawdzać błędy w domenach zabezpieczeń i symulować zestaw ataków w celu przetestowania odporności aplikacji na zabezpieczenia. Jeśli to możliwe, zintegruj to narzędzie z potokami kompilacji.

Przestrzegaj standardów branżowych dotyczących bezpiecznych praktyk kodowania. Aby uzyskać więcej informacji, zobacz sekcję Zasoby społeczności w tym artykule.

Użyj linters i analizatorów kodu, aby zapobiec wypchnięciu poświadczeń do repozytorium kodu źródłowego. Na przykład analizatory .NET Compiler Platform (Roslyn) sprawdzają kod aplikacji.

Podczas procesu kompilacji użyj dodatków potoków, aby przechwycić poświadczenia w kodzie źródłowym. Skanuj wszystkie zależności, takie jak biblioteki innych firm i składniki struktury, w ramach procesu ciągłej integracji. Zbadaj składniki podatne na zagrożenia, które są oflagowane przez narzędzie. Połącz to zadanie z innymi zadaniami skanowania kodu, które sprawdzają współczynnik zmian kodu, wyniki testów i pokrycie.

Użyj kombinacji testów. Aby uzyskać ogólne informacje na temat testowania zabezpieczeń, zobacz Zalecenia dotyczące testowania zabezpieczeń.

Napisz wystarczająco dużo kodu

Po zmniejszeniu śladu kodu można również zmniejszyć prawdopodobieństwo wystąpienia wad zabezpieczeń. Użyj ponownie kodu i bibliotek, które są już używane i zostały zweryfikowane zabezpieczeń zamiast duplikowania kodu.

Korzystanie z funkcji platformy Azure to kolejny sposób zapobiegania niepotrzebnym kodom. Jednym ze sposobów jest korzystanie z usług zarządzanych. Aby uzyskać więcej informacji, zobacz Korzystanie z opcji platformy jako usługi (PaaS).

Domyślnie napisz kod z podejściem deny-all. Utwórz listy dozwolonych tylko dla jednostek, które potrzebują dostępu. Jeśli na przykład masz kod, który musi określić, czy operacja uprzywilejowana powinna być dozwolona, należy napisać go tak, aby wynik odmowy był domyślnym przypadkiem, a wynik zezwalania występuje tylko wtedy, gdy jest to dozwolone przez kod.

Ochrona środowisk deweloperskich

Stacje robocze deweloperów muszą być chronione za pomocą silnych mechanizmów kontroli sieci i tożsamości, aby zapobiec narażeniu. Upewnij się, że aktualizacje zabezpieczeń są stosowane sumiennie.

Agenci kompilacji są wysoce uprzywilejowani i mają dostęp do serwera kompilacji i kodu. Muszą być chronione przy użyciu tej samej platformy co składniki obciążenia. Oznacza to, że dostęp do agentów kompilacji musi być uwierzytelniony i autoryzowany. Powinny one być podzielone na segmenty sieciowe za pomocą kontrolek zapory, powinny podlegać skanowaniu luk w zabezpieczeniach itd. Agenci kompilacji hostowani przez firmę Microsoft powinni być preferowani przez własnych agentów kompilacji. Agenci hostowani przez firmę Microsoft zapewniają korzyści, takie jak czyste maszyny wirtualne dla każdego uruchomienia potoku.

Agenci kompilacji niestandardowej dodają złożoność zarządzania i mogą stać się wektorem ataku. Poświadczenia maszyny kompilacji muszą być bezpiecznie przechowywane i należy regularnie usuwać wszelkie tymczasowe artefakty kompilacji z systemu plików. Można osiągnąć izolację sieci, zezwalając tylko na wychodzący ruch z agenta kompilacji, ponieważ korzysta z modelu ściągania komunikacji z usługą Azure DevOps.

Repozytorium kodu źródłowego musi być również chronione . Udzielanie dostępu do repozytoriów kodu na podstawie potrzeb i zmniejszanie narażenia na luki w zabezpieczeniach w możliwie największym stopniu w celu uniknięcia ataków. Zapoznaj się z dokładnym procesem przeglądania kodu pod kątem luk w zabezpieczeniach. Użyj grup zabezpieczeń do tego celu i zaimplementuj proces zatwierdzania oparty na uzasadnieniach biznesowych.

Wdrożenia bezpiecznego kodu

Nie wystarczy tylko zabezpieczyć kod. Jeśli działa on w potokach, które można wykorzystać, wszystkie wysiłki związane z zabezpieczeniami są bezużyteczne i niekompletne. Środowiska kompilacji i wydania muszą być również chronione , ponieważ chcesz uniemożliwić złym aktorom uruchamianie złośliwego kodu w potoku.

Utrzymywanie aktualnego spisu każdego składnika zintegrowanego z aplikacją

Każdy nowy składnik zintegrowany z aplikacją zwiększa obszar ataków. Aby zapewnić odpowiednią odpowiedzialność i alerty podczas dodawania lub aktualizowania nowych składników, należy mieć spis tych składników. Przechowuj go poza środowiskiem kompilacji. Regularnie sprawdź, czy manifest jest zgodny z tym, co znajduje się w procesie kompilacji. Dzięki temu nie są dodawane nieoczekiwanie żadne nowe składniki, które zawierają tylne drzwi lub inne złośliwe oprogramowanie.

Zadania potoku

  • Ściąganie zadań w potoku z zaufanych źródeł, takich jak Azure Marketplace. Uruchamianie zadań napisanych przez dostawcę potoku. Zalecamy wykonywanie zadań w usłudze GitHub lub GitHub Actions. Jeśli używasz przepływów pracy usługi GitHub, preferuj zadania utworzone przez firmę Microsoft. Ponadto zweryfikuj zadania, ponieważ są uruchamiane w kontekście zabezpieczeń potoku.

  • Wpisy tajne potoku. Zasoby wdrażania uruchamiane wewnątrz potoku mają dostęp do wszystkich wpisów tajnych w tym potoku. Należy mieć odpowiednie segmenty dla różnych etapów potoku , aby uniknąć niepotrzebnego narażenia. Użyj magazynów wpisów tajnych wbudowanych w potok. Pamiętaj, że w niektórych sytuacjach można unikać używania wpisów tajnych. Zapoznaj się z użyciem tożsamości obciążeń (na potrzeby uwierzytelniania potoku) i tożsamościami zarządzanymi (na potrzeby uwierzytelniania między usługami).

Zachowaj oddzielne środowiska

Dane używane w różnych środowiskach muszą być przechowywane oddzielnie. Dane produkcyjne nie powinny być używane w niższych środowiskach, ponieważ te środowiska mogą nie mieć rygorystycznych mechanizmów kontroli zabezpieczeń, które ma produkcja. Unikaj nawiązywania połączenia z nieprodukcyjnej aplikacji do produkcyjnej bazy danych i unikaj łączenia składników nieprodukcyjnych z sieciami produkcyjnymi.

Narażenie progresywne

Użyj progresywnej ekspozycji, aby zwolnić funkcje do podzestawu użytkowników na podstawie wybranych kryteriów. Jeśli występują problemy, wpływ zostanie zminimalizowany dla tych użytkowników. Takie podejście jest wspólną strategią ograniczania ryzyka, ponieważ zmniejsza obszar powierzchni. Gdy funkcja dojrzała i masz większe zaufanie do gwarancji zabezpieczeń, możesz stopniowo zwolnić ją do szerszego zestawu użytkowników.

Faza produkcji

Faza produkcji przedstawia ostatnią odpowiedzialność za rozwiązanie luk w zabezpieczeniach. Zachowaj rekord złotego obrazu wydanego w środowisku produkcyjnym.

Zachowaj wersjonowane artefakty

Zachowaj wykaz wszystkich wdrożonych zasobów i ich wersji. Te informacje są przydatne podczas klasyfikacji zdarzeń, podczas rozwiązywania problemów i powrotu systemu do stanu roboczego. Wersjonowane zasoby można również porównać z opublikowanymi powiadomieniami o typowych lukach w zabezpieczeniach i zagrożeniach (CVE). Do wykonania tych porównań należy użyć automatyzacji.

Poprawki awaryjne

Projekt zautomatyzowanego potoku powinien mieć elastyczność obsługi wdrożeń regularnych i awaryjnych. Ta elastyczność jest ważna, aby obsługiwać szybkie i odpowiedzialne poprawki zabezpieczeń.

Wydanie jest zwykle skojarzone z wieloma bramami zatwierdzania. Rozważ utworzenie procesu awaryjnego w celu przyspieszenia poprawek zabezpieczeń. Proces może obejmować komunikację między zespołami. Potok powinien umożliwiać szybkie wdrażanie wycofywania i wycofywania, które dotyczą poprawek zabezpieczeń, krytycznych usterek i aktualizacji kodu, które występują poza regularnym cyklem życia wdrażania.

Uwaga

Zawsze ustalaj priorytety poprawek zabezpieczeń nad wygodą. Poprawka zabezpieczeń nie powinna wprowadzać regresji ani usterki. Jeśli chcesz przyspieszyć poprawkę za pośrednictwem potoku awaryjnego, należy dokładnie rozważyć, które testy automatyczne można pominąć. Oceń wartość każdego testu względem czasu wykonywania. Na przykład testy jednostkowe zwykle kończą się szybko. Integracje lub kompleksowe testy mogą być uruchamiane przez długi czas.

Faza konserwacji

Celem tej fazy jest upewnienie się, że stan zabezpieczeń nie ulega rozpadowi w czasie. SDLC to ciągły proces agile. Pojęcia omówione w poprzednich fazach mają zastosowanie do tej fazy, ponieważ wymagania zmieniają się w czasie.

Zarządzanie poprawkami. Zachowaj aktualność składników oprogramowania, bibliotek i infrastruktury przy użyciu poprawek zabezpieczeń i aktualizacji.

Ciągłe ulepszanie. Stale oceniaj i poprawiaj bezpieczeństwo procesu tworzenia oprogramowania, uwzględniając przeglądy kodu, opinie, wnioski zdobyte i zmieniające się zagrożenia.

Likwiduj starsze zasoby , które są nieaktualne lub nie są już używane. Dzięki temu zmniejsza obszar powierzchni aplikacji.

Konserwacja obejmuje również poprawki zdarzeń. Jeśli problemy zostaną znalezione w środowisku produkcyjnym, należy je natychmiast zintegrować z procesem, aby nie były powtarzane.

Ciągłe ulepszanie bezpiecznych praktyk kodowania, aby nadążyć za krajobrazem zagrożeń.

Ułatwienia platformy Azure

Cykl życia programowania zabezpieczeń firmy Microsoft (SDL) zaleca bezpieczne rozwiązania, które można zastosować do cyklu projektowania. Aby uzyskać więcej informacji, zobacz Cykl programowania zabezpieczeń firmy Microsoft.

Usługa Defender for DevOps i narzędzia SAST są uwzględniane jako część GitHub Advanced Security lub Azure DevOps. Te narzędzia mogą pomóc w śledzeniu wskaźnika zabezpieczeń dla organizacji.

Postępuj zgodnie z zaleceniami dotyczącymi zabezpieczeń platformy Azure opisanymi w następujących zasobach:

Aby znaleźć poświadczenia w kodzie źródłowym, rozważ użycie narzędzi, takich jak GitHub Advanced Security i narzędzia analizy kodu źródłowego OWASP.

Zweryfikuj zabezpieczenia dowolnego kodu open source w aplikacji. Te bezpłatne narzędzia i zasoby mogą pomóc w ocenie:

Lista kontrolna zabezpieczeń

Zapoznaj się z pełnym zestawem zaleceń.