Udostępnij za pośrednictwem


Lista kontrolna bezpieczeństwa sterowników

Ten artykuł zawiera listę kontrolną zabezpieczeń dla deweloperów sterowników w celu zmniejszenia ryzyka kompromitacji sterowników.

Omówienie zabezpieczeń sterowników

Wadą zabezpieczeń jest każda wada, która pozwala atakującemu spowodować awarię sterownika w taki sposób, że prowadzi to do awarii systemu lub jego nieużywalności. Ponadto luki w zabezpieczeniach w kodzie sterownika mogą umożliwić atakującemu uzyskanie dostępu do jądra, co może spowodować naruszenie całego systemu operacyjnego. Gdy większość deweloperów pracuje nad swoim sterownikiem, koncentruje się na uzyskaniu prawidłowego działania sterownika, a nie na tym, czy złośliwy atakujący podejmie próbę wykorzystania luk w zabezpieczeniach w kodzie.

Po zwolnieniu sterownika atakujący mogą jednak próbować sondować i identyfikować wady zabezpieczeń. Deweloperzy muszą rozważyć te problemy podczas fazy projektowania i implementacji, aby zminimalizować prawdopodobieństwo wystąpienia takich luk w zabezpieczeniach. Celem jest wyeliminowanie wszystkich znanych luk w zabezpieczeniach przed wydaniem sterownika.

Tworzenie bezpieczniejszych sterowników wymaga współpracy architekta systemu (świadomego myślenia o potencjalnych zagrożeniach dla sterownika), dewelopera wdrażającego kod (defensywne kodowanie typowych operacji, które mogą być źródłem luk w zabezpieczeniach), i zespołu testowego (aktywnie próbującego znaleźć słabości i luki w zabezpieczeniach). Właściwie koordynując wszystkie te działania, bezpieczeństwo kierowcy jest znacznie ulepszone.

Oprócz uniknięcia problemów związanych z zaatakowanym sterownikiem wiele opisanych kroków, takich jak bardziej precyzyjne użycie pamięci jądra, zwiększy niezawodność sterownika. Spowoduje to zmniejszenie kosztów pomocy technicznej i zwiększenie zadowolenia klientów z produktu. Wykonanie zadań na poniższej liście kontrolnej pomoże osiągnąć wszystkie te cele.

Lista kontrolna zabezpieczeń:Ukończ zadanie zabezpieczeń opisane w każdym z tych tematów.

pole wyboru bez zaznaczenia reprezentujące element na liście kontrolnej zabezpieczeń. Upewnij się, że sterownik jądra jest wymagany

Niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Użyj struktur sterowników

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Kontrola dostępu wyłącznie do sterowników oprogramowania

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. nie używaj kodu sterownika testowego do podpisu produkcyjnego

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. przeprowadzić analizę zagrożeń

Niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Przestrzegaj wytycznych dotyczących bezpiecznego kodowania sterowników.

Niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Kod zgodny z HVCI

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Postępuj zgodnie z najlepszymi praktykami dotyczącymi kodu specyficznych dla technologii

pole wyboru bez zaznaczenia reprezentujące element na liście kontrolnej zabezpieczeń. przeprowadzenie przeglądu kodu przez współpracowników

Nieoznakowane pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Zarządzanie kontrolą dostępu do sterowników

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Ulepszanie zabezpieczeń instalacji urządzeń

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. wykonaj poprawne podpisywanie sterownika wydania

Niezaznaczone pole wyboru, które reprezentuje element na liście kontrolnej zabezpieczeń. Użyj CodeQL, aby sprawdzić kod sterownika

niezaznaczone pole wyboru symbolizujące element na liście kontrolnej zabezpieczeń. dodaj adnotacje SAL do kodu sterownika

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Użyj Weryfikatora Sterowników do sprawdzenia luk w zabezpieczeniach

Niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Sprawdź kod za pomocą narzędzia „BinSkim Binary Analyzer”

pole wyboru bez znacznika reprezentujące element na liście kontrolnej zabezpieczeń. Sprawdź kod przy użyciu testów zgodności sprzętu

Niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Dowiedz się, jak sterowniki są zgłaszane przy użyciu Centrum Zgłaszania Sterowników Podatnych i Złośliwych firmy Microsoft

niezaznaczone pole wyboru reprezentujące element na liście kontrolnej zabezpieczeń. Przeglądanie zasobów dotyczących bezpiecznego kodowania

Nieoznaczone pole wyboru, które reprezentuje element na liście kontrolnej zabezpieczeń. Przejrzyj Podsumowanie najważniejszych wniosków

Upewnij się, że sterownik jądra jest wymagany

element listy kontrolnej zabezpieczeń nr 1:Upewnij się, że sterownik jądra jest wymagany i że podejście niższego ryzyka, takie jak usługa lub aplikacja systemu Windows, nie jest lepszym rozwiązaniem.

Sterowniki działają w jądrze systemu Windows, a wystąpienie problemu podczas wykonywania w jądrze naraża na niebezpieczeństwo cały system operacyjny. Jeśli jakakolwiek inna opcja jest dostępna, prawdopodobnie będzie ona niższa i będzie miała mniejsze ryzyko niż utworzenie nowego sterownika jądra. Aby uzyskać więcej informacji na temat korzystania z wbudowanych sterowników systemu Windows, zobacz Czy musisz napisać sterownik?.

Aby uzyskać informacje na temat korzystania z zadań w tle, zobacz Support your app with background tasks (Obsługa aplikacji przy użyciu zadań w tle).

Aby uzyskać informacje na temat korzystania z usług systemu Windows, zobacz Services.

Korzystanie ze struktur sterowników

element listy kontrolnej zabezpieczeń nr 2:Użyj struktur sterowników, aby zmniejszyć rozmiar kodu i zwiększyć jego niezawodność i bezpieczeństwo.

Użyj Windows Driver Frameworks, aby zmniejszyć rozmiar kodu i zwiększyć jego niezawodność i bezpieczeństwo. Aby rozpocząć, zapoznaj się z artykułem Using WDF to Develop a Driver(Używanie usługi WDF do tworzenia sterownika). Aby uzyskać informacje na temat używania sterownika struktury trybu użytkownika niższego ryzyka (UMDF), zobacz Wybieranie modelu sterowników.

Pisanie sterownika w starym modelu Windows Driver Model (WDM) jest bardziej czasochłonne, kosztowne i prawie zawsze wiąże się z ponownym tworzeniem kodu dostępnego w frameworkach sterowników.

Kod źródłowy struktury sterowników systemu Windows jest typu open source i dostępny w witrynie GitHub. Jest to ten sam kod źródłowy, z którego jest skompilowana biblioteka środowiska uruchomieniowego usługi WDF dostarczana w systemie Windows 10. Możesz efektywniej debugować sterownik, gdy możesz śledzić interakcje między sterownikiem a usługą WDF. Pobierz go z https://github.com/Microsoft/Windows-Driver-Frameworks.

Kontrolowanie dostępu tylko do sterowników oprogramowania

element listy kontrolnej zabezpieczeń nr 3:Jeśli sterownik tylko do oprogramowania zostanie utworzony, należy zaimplementować dodatkową kontrolę dostępu.

Sterowniki jądra bazujące wyłącznie na oprogramowaniu nie używają plug-and-play (PnP) do powiązania się z konkretnymi identyfikatorami sprzętu i mogą działać na dowolnym komputerze. Taki sterownik może być używany do celów innych niż pierwotnie przewidziane, tworząc wektor ataku.

Ponieważ sterowniki jądra tylko w oprogramowaniu zawierają dodatkowe ryzyko, muszą być ograniczone do uruchamiania na określonym sprzęcie (na przykład przy użyciu unikatowego identyfikatora PnP w celu umożliwienia tworzenia sterownika PnP lub sprawdzając tabelę SMBIOS pod kątem obecności określonego sprzętu).

Załóżmy na przykład, że firma OEM Fabrikam chce dystrybuować sterownik, który umożliwia narzędzie do podkręcania dla swoich systemów. Jeśli ten sterownik tylko do oprogramowania miał zostać wykonany w systemie z innego producenta OEM, może to spowodować niestabilność systemu lub uszkodzenie. Systemy firmy Fabrikam powinny zawierać unikatowy identyfikator PnP, aby umożliwić tworzenie sterownika PnP, który jest również aktualizowalny za pośrednictwem usługi Windows Update. Jeśli nie jest to możliwe, a firma Fabrikam tworzy starszy sterownik, ten sterownik powinien znaleźć inną metodę, aby sprawdzić, czy jest on wykonywany w systemie Fabrikam (na przykład przez zbadanie tabeli SMBIOS przed włączeniem jakichkolwiek możliwości).

Nie należy pisać w środowisku produkcyjnym kodu testowego

element listy kontrolnej zabezpieczeń nr 4:Nie podpisuj produkcyjnie kodu sterownika jądra w fazie rozwoju, testowania oraz produkcji.

Kod sterownika jądra używany do programowania, testowania lub produkcji może obejmować niebezpieczne możliwości, które stanowią zagrożenie bezpieczeństwa. Ten niebezpieczny kod nigdy nie powinien być podpisany przy użyciu certyfikatu zaufanego przez system Windows. Prawidłowym mechanizmem wykonywania niebezpiecznego kodu sterownika jest wyłączenie bezpiecznego rozruchu UEFI, włączenie funkcji BCD "TESTSIGNING" i podpisanie kodu programistycznego, testowego i produkcyjnego przy użyciu niezaufanego certyfikatu (na przykład jednego wygenerowanego przez makecert.exe).

Kod podpisany przez zaufany certyfikat wydawców oprogramowania (SPC) lub sygnaturę WHQL (Hardware Quality Labs) systemu Windows nie może ułatwić obejścia technologii integralności kodu i zabezpieczeń systemu Windows. Zanim kod zostanie podpisany przez zaufany podpis SPC lub WHQL, upewnij się najpierw, że jest zgodny ze wskazówkami z dotyczących tworzenia niezawodnych sterowników Kernel-Mode. Ponadto kod nie może zawierać żadnych niebezpiecznych zachowań opisanych poniżej. Aby uzyskać więcej informacji na temat podpisywania sterowników, zobacz Podpisywanie sterownika wydanego w dalszej części artykułu.

Przykłady niebezpiecznego zachowania obejmują następujące elementy:

  • Umożliwia mapowanie dowolnego jądra, pamięci fizycznej lub pamięci urządzenia na tryb użytkownika.
  • Zapewnienie możliwości odczytu lub zapisu dowolnej pamięci jądra, fizycznej lub urządzenia, w tym wejścia/wyjścia portu (I/O).
  • Zapewnianie dostępu do przechowywania, które omija kontrolę dostępu systemu Windows.
  • Zapewnienie możliwości modyfikowania sprzętu lub oprogramowania układowego, którym sterownik nie został zaprojektowany do zarządzania.

Przeprowadzanie analizy zagrożeń

punkt listy kontrolnej zabezpieczeń nr 5:Zmodyfikuj istniejący model zagrożenia sterownika lub utwórz niestandardowy model zagrożenia dla sterownika.

Biorąc pod uwagę bezpieczeństwo, wspólną metodologią jest utworzenie konkretnych modeli zagrożeń, które próbują opisać możliwe typy ataków. Ta technika jest przydatna podczas projektowania sterownika, ponieważ zmusza programistę do rozważenia potencjalnych wektorów ataku z wyprzedzeniem. Po zidentyfikowaniu potencjalnych zagrożeń deweloper może następnie rozważyć środki obrony przed tymi zagrożeniami, aby wzmocnić ogólne bezpieczeństwo składnika sterownika.

Ten artykuł zawiera specjalistyczne wskazówki dla sterowników dotyczące tworzenia lekkiego modelu zagrożeń: Modelowanie zagrożeń dla sterowników. Artykuł zawiera przykładowy diagram modelu zagrożeń sterownika, który może być używany jako punkt wyjścia dla twojego sterownika.

Przykładowy diagram przepływu danych ilustrujący hipotetyczny sterownik trybu jądra.

Najlepsze praktyki dotyczące cyklu projektowania zabezpieczeń (SDL) i powiązane narzędzia mogą być wykorzystywane przez dostawców sprzętu (IHV) i producentów OEM w celu poprawy bezpieczeństwa swoich produktów. Więcej informacji można znaleźć w zaleceniach SDL dla producentów OEM.

Postępuj zgodnie z wytycznymi dotyczącymi bezpiecznego kodowania sterowników

element listy kontrolnej zabezpieczeń nr 6:Przejrzyj kod i usuń wszelkie znane luki w zabezpieczeniach kodu.

Głównym działaniem tworzenia bezpiecznych sterowników jest identyfikowanie obszarów w kodzie, które należy zmienić, aby uniknąć znanych luk w zabezpieczeniach oprogramowania. Wiele z tych znanych luk w zabezpieczeniach oprogramowania dotyczy ścisłego monitorowania użycia pamięci, aby uniknąć problemów z innymi nadpisywaniem lub w inny sposób kompromitującymi lokalizacjami pamięci używanymi przez sterownik.

Narzędzia do skanowania kodu, takie jak CodeQL i testy specyficzne dla sterowników, mogą służyć do lokalizowania niektórych, ale nie wszystkich tych luk w zabezpieczeniach. Te narzędzia i testy zostały opisane w dalszej części tego tematu.

bufory pamięci

Użyj odpowiedniej metody uzyskiwania dostępu do buforów danych za pomocą IOCTL

Jedną z podstawowych obowiązków sterownika systemu Windows jest transferowanie danych między aplikacjami w trybie użytkownika a urządzeniami systemu. W poniższej tabeli przedstawiono trzy metody uzyskiwania dostępu do danych.

Typ buforu IOCTL Streszczenie Aby uzyskać więcej informacji
METHOD_BUFFERED Zalecane w przypadku większości situtacji Korzystanie z buforowanego we/wy
METHOD_IN_DIRECT lub METHOD_OUT_DIRECT Używane w niektórych szybkich we/wy HW Przy użyciu bezpośredniego I/O
METODA_BRAK Unikaj, jeśli jest to możliwe Używanie ani buforowanych, ani bezpośrednich operacji we/wy

Ogólnie rzecz biorąc, buforowane we/wy zaleca się, ponieważ zapewnia najbezpieczniejsze metody buforowania. Jednak nawet w przypadku użycia buforowanych operacji we/wy istnieją zagrożenia, takie jak osadzone wskaźniki w pamięci, które trzeba uwzględnić.

Aby uzyskać więcej informacji na temat pracy z buforami w IOCTLs, zobacz Metody uzyskiwania dostępu do buforów danych.

Błędy w użyciu buforowanego I/O IOCTL

  • Sprawdź rozmiar buforów związanych z IOCTL. Aby uzyskać więcej informacji, zobacz Niepowodzenie sprawdzania rozmiaru bufforów.

  • Poprawnie zainicjuj bufory wyjściowe. Aby uzyskać więcej informacji, zobacz Błąd inicjowania buforów wyjściowych.

  • Poprawnie zweryfikuj bufory o zmiennej długości. Aby uzyskać więcej informacji, zobacz Niepowodzenie walidacji buforów Variable-Length.

  • W przypadku korzystania z buforowanych operacji we/wy upewnij się, aby w polu Informacje struktury IO_STATUS_BLOCK zwrócić odpowiednią długość dla elementu OutputBuffer. Nie zwracaj bezpośrednio długości z żądania odczytu. Rozważmy na przykład sytuację, w której zwrócone dane z przestrzeni użytkownika wskazują, że istnieje bufor 4K. Jeśli sterownik powinien zwracać tylko 200 bajtów, ale zamiast tego zwraca wartość 4K w polu Informacje, wystąpiła luka w zabezpieczeniach umożliwiająca ujawnienie informacji. Ten problem występuje, ponieważ we wcześniejszych wersjach systemu Windows bufor używany przez Menedżera we/wy dla operacji buforowanych nie jest zerowany. W związku z tym aplikacja użytkownika odzyskuje oryginalne 200 bajtów danych plus 4K - 200 bajtów tego, co znajdowało się w buforze (zawartości puli niestronicowanej). Ten scenariusz może wystąpić ze wszystkimi zastosowaniami buforowanych operacji we/wy, a nie tylko z IOCTLs.

Błędy w bezpośrednim we/wy IOCTL

Poprawnie obsługuj bufory o zerowej długości. Aby uzyskać więcej informacji, zobacz Errors in Direct I/O.

Błędy podczas odwoływania się do adresów przestrzeni użytkownika

  • Zweryfikuj wskaźniki osadzone w buforowanych żądaniach wejścia/wyjścia. Aby uzyskać więcej informacji, zobacz Errors in Referencing User-Space Addresses.

  • Przed podjęciem próby użycia zweryfikuj dowolny adres w przestrzeni użytkownika, używając interfejsów API, takich jak ProbeForRead i ProbeForWrite, jeśli to stosowne.

Rejestr specyficzny dla modelu MSR - odczyty i zapisy

Funkcje wewnętrzne kompilatora, takie jak __readmsr i __writemsr, mogą służyć do uzyskiwania dostępu do rejestrów specyficznych dla modelu. Jeśli ten dostęp jest wymagany, sterownik musi zawsze sprawdzić, czy rejestr do odczytu lub zapisu jest ograniczony do oczekiwanego indeksu lub zakresu.

Aby uzyskać więcej informacji i przykłady kodu, zobacz Zapewnianie możliwości odczytu/zapisu MSR w Najlepsze rozwiązania dotyczące ograniczania zachowania o wysokim poziomie uprawnień w sterownikach trybu jądra.

Luki w zabezpieczeniach TOCTOU

Istnieje potencjalny czas sprawdzania czasu użycia (TOCTOU) luki w zabezpieczeniach podczas używania bezpośredniego we/wy (w przypadku IOCTLs lub odczytu/zapisu). Należy pamiętać, że sterownik uzyskuje dostęp do buforu danych użytkownika, użytkownik może jednocześnie uzyskiwać do niego dostęp.

Aby zarządzać tym ryzykiem, skopiuj wszystkie parametry, które należy zweryfikować z buforu danych użytkownika do pamięci, która jest dostępna wyłącznie z trybu jądra (na przykład stos lub pula). Następnie, gdy nie będzie można uzyskać dostępu do danych przez aplikację użytkownika, zweryfikuj, a następnie przeprowadź operację na przekazanych danych.

Kod sterownika musi mieć poprawne wykorzystanie pamięci

  • Wszystkie alokacje puli sterowników muszą znajdować się w puli nie wykonywalnej (NX). Korzystanie z pul pamięci NX jest z natury bezpieczniejsze niż korzystanie z wykonywalnych pul niestronicowanych (NP) i zapewnia lepszą ochronę przed atakami przepełnienia.

  • Sterowniki urządzeń muszą prawidłowo obsługiwać różne żądania z poziomu użytkownika, jak również żądania we/wy między jądrem a jądrem.

Aby umożliwić sterownikom obsługę wirtualizacji HVCI, istnieją dodatkowe wymagania dotyczące pamięci. Aby uzyskać więcej informacji, zobacz Implementowanie kodu zgodnego z standardem HVCI w dalszej części tego artykułu.

Uchwyty

Obiekty urządzeń

IRPs

WDF i IRPs

Jedną z zalet korzystania z usługi WDF jest to, że sterowniki WDF zwykle nie uzyskują bezpośredniego dostępu do IRP. Na przykład framework konwertuje IRP WDM reprezentujące operacje odczytu, zapisu oraz sterowania urządzeń I/O na obiekty żądań, które są odbierane przez KMDF/UMDF w kolejkach I/O.

Jeśli piszesz sterownik WDM, zapoznaj się z poniższymi wskazówkami.

Prawidłowe zarządzanie buforami we/wy IRP

Następujące artykuły zawierają informacje o weryfikowaniu wartości wejściowych protokołu IRP:

DispatchReadWrite przy użyciu buforowanego I/O

Błędy w buforowanym We/Wy

DispatchReadWrite przy użyciu bezpośredniego we/wy

Błędy w bezpośrednim we/wy

Kwestie Bezpieczeństwa dla Kodów Kontroli We/Wy

Rozważ zweryfikowanie wartości skojarzonych z IRP, takich jak adresy buforów i długości.

Jeśli zdecydujesz się używać Neither I/O, należy pamiętać, że w przeciwieństwie do operacji odczytu i zapisu oraz w przeciwieństwie do buforowanych i bezpośrednich operacji wejścia/wyjścia, przy korzystaniu z Neither I/O, wskaźniki buforu i długości nie są weryfikowane przez Menedżera I/O.

Prawidłowe obsługa operacji uzupełniania IRP

Sterownik nigdy nie może ukończyć protokołu IRP z wartością stanu STATUS_SUCCESS, chyba że faktycznie obsługuje i przetwarza protokół IRP. Aby uzyskać informacje o prawidłowych sposobach obsługi operacji zakończenia IRP, zobacz Kończenie IRP.

Zarządzanie stanem oczekiwania protokołu IRP sterownika

Sterownik powinien oznaczyć oczekujący IRP przed jego zapisaniem i rozważyć uwzględnienie zarówno wywołania IoMarkIrpPending, jak i przypisania w zsynchronizowanej sekwencji. Aby uzyskać więcej informacji, zobacz Niepowodzenie sprawdzania stanu sterownika i wstrzymywanie przychodzących IRP po wstrzymaniu urządzenia.

Prawidłowo obsłuż operacje anulowania IRP

Operacje anulowania mogą być trudne do poprawnego kodowania, ponieważ zwykle są wykonywane asynchronicznie. Problemy w kodzie, który obsługuje operacje anulowania, mogą być niezauważone przez długi czas, ponieważ ten kod zwykle nie jest wykonywany często w uruchomionym systemie. Pamiętaj, aby zapoznać się ze wszystkimi informacjami podanymi w Anulowanie IRPs. Zwróć szczególną uwagę na Synchronizowanie anulowania IRP-ów oraz kwestie, które należy wziąć pod uwagę podczas anulowania IRP-ów.

Zalecanym sposobem zminimalizowania problemów z synchronizacją skojarzonych z operacjami anulowania jest zaimplementowanie kolejki IRP z bezpiecznym anulowaniem.

Prawidłowo obsługuj czyszczenie i zamykanie operacji IRP

Upewnij się, że rozumiesz różnicę między żądaniami IRP_MJ_CLEANUP i IRP_MJ_CLOSE. Żądania czyszczenia są dostarczane po zamknięciu wszystkich uchwytów w obiekcie pliku, jednak czasami przed zakończeniem wszystkich żądań we/wy. Żądania zamknięcia docierają po zakończeniu lub anulowaniu wszystkich żądań we/wy dla obiektu pliku. Aby uzyskać więcej informacji, zobacz następujące artykuły:

DispatchCreate, DispatchClose i DispatchCreateClose Rutyny

Procedury sprzątania

błędy obsługi operacji oczyszczania i zamykania

Aby uzyskać więcej informacji na temat prawidłowego obsługi IRP, zobacz Dodatkowe błędy w obsłudze IRP.

Inne problemy z zabezpieczeniami

  • Użyj blokady lub sekwencji wzajemnego blokowania, aby zapobiec warunkom wyścigu. Aby uzyskać więcej informacji, zobacz błędy w środowisku wieloprocesorowym.

  • Upewnij się, że sterowniki urządzeń prawidłowo obsługują różne żądania trybu użytkownika, a także żądania wejścia/wyjścia jądro do jądra.

  • Upewnij się, że podczas instalacji lub użycia nie są instalowane żadne filtry TDI ani dostawcy LSP ani powiązane pakiety oprogramowania.

Korzystanie z bezpiecznych funkcji

Dodatkowe luki w zabezpieczeniach kodu

Oprócz możliwych luk w zabezpieczeniach omówionych tutaj ten artykuł zawiera dodatkowe informacje na temat zwiększania zabezpieczeń kodu sterownika trybu jądra: Tworzenie niezawodnych sterowników Kernel-Mode.

Aby uzyskać dodatkowe informacje na temat bezpiecznego kodowania w języku C i C++, zobacz Bezpieczne zasoby kodowania na końcu tego artykułu.

Zarządzanie kontrolą dostępu kierowców

element listy kontrolnej zabezpieczeń nr 7:Sprawdź sterownik, aby upewnić się, że masz prawidłową kontrolę dostępu.

Zarządzanie kontrolą dostępu do sterowników — WDF

Sterowniki muszą działać, aby uniemożliwić użytkownikom niewłaściwy dostęp do urządzeń i plików komputera. Aby zapobiec nieautoryzowanemu dostępowi do urządzeń i plików, należy:

  • Nazwij obiekty urządzeń tylko wtedy, gdy jest to konieczne. Obiekty urządzeń z nazwami są zazwyczaj potrzebne tylko z powodów zgodności z przeszłością, na przykład, jeśli masz aplikację, która oczekuje, że otworzy urządzenie przy użyciu określonej nazwy, lub jeśli używasz urządzenia innego niż PNP lub urządzenia sterującego. Należy pamiętać, że sterowniki WDF nie muszą nazywać swoich urządzeń PnP jako FDO, aby utworzyć link symboliczny przy użyciu WdfDeviceCreateSymbolicLink.

  • Bezpieczny dostęp do obiektów i interfejsów urządzeń.

Aby zezwolić aplikacjom lub innym sterownikom WDF na dostęp do PDO urządzenia PnP, należy użyć interfejsów urządzeń. Aby uzyskać więcej informacji, zobacz Korzystanie z interfejsów urządzeń. Interfejs urządzenia służy jako symboliczne łącze do PDO stosu urządzeń.

Jednym z lepszych sposobów kontrolowania dostępu do obiektu PDO jest określenie ciągu SDDL w INF. Jeśli ciąg SDDL nie znajduje się w pliku INF, system Windows zastosuje domyślny deskryptor zabezpieczeń. Aby uzyskać więcej informacji, zobacz Zabezpieczanie obiektów urządzeń i SDDL dla obiektów urządzeń.

Aby uzyskać więcej informacji na temat kontrolowania dostępu, zobacz następujące artykuły:

kontrolowanie dostępu do urządzeń w sterownikach KMDF

Nazwy, deskryptory zabezpieczeń i klasy urządzeń — udostępnianie obiektów urządzeń... i bezpieczne od stycznia lutego 2017 r. biuletyn NT Insider opublikowany przez OSR.

Zarządzanie kontrolą dostępu do sterowników — WDM

Jeśli pracujesz ze sterownikiem WDM i użyto nazwanego obiektu urządzenia, możesz użyć IoCreateDeviceSecure i określić sdDL, aby go zabezpieczyć. Podczas implementacji IoCreateDeviceSecure zawsze określaj niestandardowy identyfikator GUID dla DeviceClassGuid. Nie należy tutaj określać istniejącego identyfikatora GUID klasy. W ten sposób istnieje możliwość przerwania ustawień zabezpieczeń lub zgodności dla innych urządzeń należących do tej klasy. Aby uzyskać więcej informacji, zobacz WdmlibIoCreateDeviceSecure.

Aby uzyskać więcej informacji, zobacz następujące artykuły:

Zarządzanie dostępem do urządzeń

Kontrolowanie dostępu do przestrzeni nazw urządzeń

model zabezpieczeń systemu Windows dla deweloperów sterowników

Hierarchia ryzyka identyfikatorów zabezpieczeń (SID)

W poniższej sekcji opisano hierarchię ryzyka typowych identyfikatorów SID używanych w kodzie sterownika. Aby uzyskać ogólne informacje na temat języka SDDL, zobacz SDDL for Device Objects, SID Stringsi SDDL String Syntax.

Należy pamiętać, że jeśli osoby wywołujące niższe uprawnienia mogą uzyskiwać dostęp do jądra, zwiększa się ryzyko związane z kodem. Na tym diagramie podsumowania ryzyko zwiększa się w miarę zezwalania identyfikatorom zabezpieczeń (SID) z niższymi uprawnieniami na dostęp do funkcjonalności sterownika.

SY (System)
\/
BA (Built-in Administrators)
\/
LS (Local Service)
\/
BU (Built-in User)
\/
AC (Application Container)

Zgodnie z ogólną zasadą zabezpieczeń najniższych uprawnień skonfiguruj tylko minimalny poziom dostępu wymagany do działania sterownika.

Szczegółowa kontrola zabezpieczeń na poziomie IOCTL WDM

Aby dodatkowo zarządzać zabezpieczeniami podczas wysyłania poleceń IOCTL przez programy w trybie użytkownika, kod sterownika może zawierać funkcję IoValidateDeviceIoControlAccess. Ta funkcja umożliwia sterownikowi sprawdzanie praw dostępu. Po otrzymaniu IOCTL sterownik może wywołać IoValidateDeviceIoControlAccess, określając FILE_READ_ACCESS, FILE_WRITE_ACCESS lub oba.

Implementowanie szczegółowej kontroli zabezpieczeń IOCTL nie zastępuje potrzeby zarządzania dostępem sterowników przy użyciu technik omówionych powyżej.

Aby uzyskać więcej informacji, zobacz następujące artykuły:

definiowanie kodów kontrolek we/wy

Implementowanie kodu zgodnego z standardem HVCI

element listy kontrolnej zabezpieczeń #8:Sprawdź, czy sterownik używa pamięci, aby był zgodny z standardem HVCI.

Użycie pamięci i zgodność Z standardem HVCI

Technologia HVCI używa technologii sprzętowej i wirtualizacji do izolowania funkcji podejmowania decyzji dotyczących integralności kodu (CI) od pozostałej części systemu operacyjnego. W przypadku korzystania z zabezpieczeń opartych na wirtualizacji w celu izolowania integralności przepływu sterowania, jedynym sposobem, w jaki pamięć jądra może stać się wykonywalna, jest weryfikacja integralności przepływu sterowania. Oznacza to, że strony pamięci jądra nigdy nie mogą być zapisywalne i wykonywalne (W+X) i nie można bezpośrednio modyfikować kodu wykonywalnego.

Aby zaimplementować kod zgodny z standardem HVCI, upewnij się, że kod sterownika wykonuje następujące czynności:

  • Domyślnie włącza NX
  • Używa interfejsów API NX i flag do alokacji pamięci (NonPagedPoolNx)
  • Nie używa sekcji, które są zarówno zapisywalne, jak i wykonywalne
  • Nie próbuje bezpośrednio modyfikować pamięci systemu wykonywalnego
  • Nie używa kodu dynamicznego w jądrze
  • Nie ładuje plików danych jako pliku wykonywalnego
  • Wyrównanie sekcji to wielokrotność 0x1000 (PAGE_SIZE). Na przykład DRIVER_ALIGNMENT=0x1000

Aby uzyskać więcej informacji na temat używania narzędzia i listy niezgodnych wywołań pamięci, zobacz Implementowanie kodu zgodnego z standardem HVCI.

Aby uzyskać więcej informacji na temat powiązanego testu zabezpieczeń systemu podstawowego, zobacz test gotowości integralności kodu funkcji HyperVisor i Hypervisor-Protected integralność kodu (HVCI).

Postępuj zgodnie z najlepszymi rozwiązaniami dotyczącymi kodu specyficznymi dla technologii

element listy kontrolnej zabezpieczeń nr 9:Zapoznaj się z następującymi wskazówkami dotyczącymi technologii dla sterownika.

Systemy plików

Aby uzyskać więcej informacji na temat zabezpieczeń sterowników systemu plików, zobacz następujące artykuły:

Wprowadzenie do zabezpieczeń systemów plików

problemy z zabezpieczeniami systemu plików

funkcje zabezpieczeń dla systemów plików

współistnienie z innymi sterownikami filtrów systemu plików

NDIS — technologie sieciowe

Aby uzyskać informacje o zabezpieczeniach sterowników NDIS, zobacz Problemy z zabezpieczeniami sterowników sieciowych.

Wyświetlacz

Aby uzyskać informacje na temat zabezpieczeń sterownika wyświetlania, zobacz <Content Pending>.

Drukarki

Aby uzyskać informacje dotyczące zabezpieczeń sterowników drukarek, zobacz Zagadnienia dotyczące zabezpieczeń sterowników drukarek V4.

Problemy z zabezpieczeniami sterowników pozyskiwania obrazów systemu Windows (WIA)

Aby uzyskać informacje na temat zabezpieczeń WIA, zapoznaj się z Problemy zabezpieczeń dla sterowników Windows Image Acquisition (WIA).

Ulepszanie zabezpieczeń instalacji urządzeń

element listy kontrolnej zabezpieczeń #10:Zapoznaj się z wytycznymi dotyczącymi tworzenia i instalacji sterownika, aby upewnić się, że przestrzegasz najlepszych praktyk.

Podczas tworzenia kodu, który instaluje sterownik, należy upewnić się, że instalacja urządzenia będzie zawsze wykonywana w bezpieczny sposób. Bezpieczna instalacja urządzenia jest taka, która wykonuje następujące czynności:

  • Ogranicza dostęp do urządzenia i jego klas interfejsów urządzeń
  • Ogranicza dostęp do usług sterowników utworzonych dla urządzenia
  • Chroni pliki sterowników przed modyfikacją lub usunięciem
  • Ogranicza dostęp do wpisów rejestru urządzenia
  • Ogranicza dostęp do klas WMI urządzenia
  • Prawidłowo używa funkcji SetupAPI

Aby uzyskać więcej informacji, zobacz następujące artykuły:

tworzenie bezpiecznych instalacji urządzeń

wskazówki dotyczące używania interfejsu SetupAPI

przy użyciu funkcji instalacji urządzeń

Zaawansowane tematy dotyczące instalacji urządzeń i sterowników

Przegląd kodu przez kolegów

element listy kontrolnej zabezpieczeń nr 11:Przeprowadzanie przeglądu kodu równorzędnego, aby wyszukać problemy, które nie są udostępniane przez inne narzędzia i procesy

Poszukaj wiedzy recenzentów kodu, aby wyszukać problemy, które mogły zostać pominięte. Drugi zestaw oczu często widzi problemy, które mogą być pomijane.

Jeśli nie masz odpowiedniego personelu, aby przejrzeć kod wewnętrznie, rozważ zaangażowanie zewnętrznej pomocy w tym celu.

Wykonywanie prawidłowego podpisywania sterownika wydania

element listy kontrolnej zabezpieczeń nr 12:Użyj portalu partnerskiego systemu Windows, aby prawidłowo podpisać sterownik do dystrybucji.

Przed wydaniem pakietu sterowników do publicznej wiadomości zaleca się przesłanie pakietu do certyfikacji. Aby uzyskać więcej informacji, zobacz Test pod kątem wydajności i zgodności, Rozpoczynanie pracy z programem sprzętowym, Usługi pulpitu sprzętowegoi Podpisywanie sterownika jądra dla publicznego wydania.

Sprawdzanie kodu sterownika za pomocą języka CodeQL

element listy kontrolnej zabezpieczeń nr 13:Sprawdzanie luk w zabezpieczeniach w kodzie sterownika za pomocą języka CodeQL.

CodeQL firmy GitHub to aparat analizy kodu semantycznego, a kombinacja rozbudowanego zestawu zapytań zabezpieczeń wraz z niezawodną platformą sprawia, że jest to bezcenne narzędzie do zabezpieczania kodu sterownika. Więcej informacji można znaleźć w CodeQL i Teście Logo Narzędzi Statycznych.

Dodawanie adnotacji SAL do kodu sterownika

element listy kontrolnej zabezpieczeń nr 14:Dodaj adnotacje SAL do w kodzie sterownika.

Język adnotacji kodu źródłowego (SAL) udostępnia zestaw adnotacji, których można użyć do opisania sposobu używania jego parametrów przez funkcję, założeń, które wykonuje na ich temat, oraz gwarancji, które wykonuje po zakończeniu. Adnotacje są definiowane w pliku nagłówka sal.h. Analiza kodu programu Visual Studio dla języka C++ używa adnotacji SAL do modyfikowania analizy funkcji. Aby uzyskać więcej informacji na temat SAL 2.0 do tworzenia sterowników Windows, zobacz Adnotacje SAL 2.0 dla sterowników Windows i Używanie adnotacji SAL w celu zmniejszenia wad kodu C/C++.

Aby uzyskać ogólne informacje na temat SAL, zapoznaj się z tym artykułem dostępnym w OSR. https://www.osr.com/blog/2015/02/23/sal-annotations-dont-hate-im-beautiful/

Sprawdzanie luk w zabezpieczeniach za pomocą weryfikatora sterowników

element listy kontrolnej zabezpieczeń nr 15:Użyj weryfikatora sterowników, aby sprawdzić luki w zabezpieczeniach w kodzie sterownika.

Weryfikator sterowników używa zestawu reguł interfejsu i modelu systemu operacyjnego w celu określenia, czy sterownik prawidłowo współdziała z systemem operacyjnym Windows. DV znajduje wady w kodzie sterownika, które mogą wskazywać na potencjalne błędy w sterownikach.

Weryfikator sterowników umożliwia testowanie na żywo sterownika. Weryfikator sterowników monitoruje sterowniki trybu jądra systemu Windows i sterowniki graficzne w celu wykrywania nielegalnych wywołań funkcji lub akcji, które mogą uszkodzić system. Weryfikator sterowników może poddać sterowniki systemu Windows różnym stresom i testom w celu znalezienia nieprawidłowego zachowania. Aby uzyskać więcej informacji, zobacz Driver Verifier.

Należy pamiętać, że tylko niektóre typy sterowników są obsługiwane przez DV. Aby uzyskać więcej informacji na temat sterowników, które może zweryfikować DV, zobacz Obsługiwane sterowniki. Zapoznaj się z następującymi stronami, aby uzyskać informacje na temat testów DV dostępnych dla typu sterownika, z którym pracujesz.

Aby zapoznać się z DV, możesz użyć jednego z przykładowych sterowników (na przykład polecanego przykładowego sterownika toster: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).

Sprawdź kod za pomocą analizatora BinSkim Binary Analyzer

element listy kontrolnej zabezpieczeń nr 16:Wykonaj następujące kroki, aby użyć binSkim, aby dokładnie sprawdzić, czy opcje kompilacji i kompilacji są skonfigurowane w celu zminimalizowania znanych problemów z zabezpieczeniami.

Użyj BinSkim, aby przeanalizować pliki binarne i zidentyfikować techniki kodowania oraz budowania, które mogą czynić binarne podatnymi na zagrożenia.

BinSkim sprawdza:

  • Korzystanie z nieaktualnych zestawów narzędzi kompilatora — pliki binarne powinny być kompilowane względem najnowszych zestawów narzędzi kompilatora, gdzie tylko jest to możliwe, aby zmaksymalizować wykorzystanie bieżących środków zaradczych dotyczących zabezpieczeń na poziomie kompilatora i systemu operacyjnego.
  • Niezabezpieczone ustawienia kompilacji — pliki binarne powinny być kompilowane przy użyciu najbezpieczniejszych ustawień umożliwiających ograniczenie zabezpieczeń zapewnianych przez system operacyjny, maksymalizowanie błędów kompilatora i raportowanie ostrzeżeń z możliwością działania.
  • Problemy z podpisywaniem — podpisane pliki binarne powinny być podpisane przy użyciu algorytmów kryptograficznie silnych.

BinSkim to narzędzie typu open source i generuje pliki wyjściowe korzystające z formatu wymiany wyników analizy statycznej (SARIF). BinSkim zastępuje poprzednie narzędzie BinScope.

Aby uzyskać więcej informacji na temat BinSkim, zobacz Użyj BinSkim, aby sprawdzić pliki binarne oraz Przewodnik użytkownika BinSkim.

Sprawdzanie kodu przy użyciu testów programu zgodności sprzętu

element listy kontrolnej zabezpieczeń nr 17:Użyj testów programu zgodności sprzętu powiązanego z zabezpieczeniami, aby sprawdzić, czy występują problemy z zabezpieczeniami.

Program zgodności sprzętu zawiera testy związane z zabezpieczeniami, które mogą służyć do wyszukiwania luk w zabezpieczeniach kodu. Program zgodności sprzętu systemu Windows korzysta z testów w zestawie Windows Hardware Lab Kit (HLK). Testy podstawowe urządzeń HLK mogą być używane w wierszu poleceń do wykonywania kodu sterownika i wyszukiwania słabości. Aby uzyskać ogólne informacje na temat testów podstawowych urządzeń i programu zgodności sprzętu, zobacz Windows Hardware Lab Kit.

Poniższe testy to przykłady testów, które mogą być przydatne do sprawdzania kodu sterownika pod kątem niektórych zachowań związanych z lukami w zabezpieczeniach kodu:

DF — test rozmyty losowego testu IOCTL (niezawodność)

DF - Test otwarć podrozmytych (niezawodność)

DF — test bufora o zerowej długości FSCTL (niezawodność)

DF — rozmyty losowy test FSCTL (niezawodność)

DF — test interfejsu API rozmytego (niezawodność)

Można również użyć fuzzing opóźnienia synchronizacji jądra, które jest dołączone do Weryfikatora Sterowników.

Testy CHAOS (Concurrent Hardware and Operating System) uruchamiają współbieżnie różne testy sterowników PnP, fuzz testing sterowników urządzeń oraz testy systemu zasilania. Aby uzyskać więcej informacji, zobacz testy CHAOS (Podstawy Urządzeń).

Testy penetracyjne Device Fundamentals przeprowadzają różne formy ataków wejściowych, które są krytycznym składnikiem testowania zabezpieczeń. Testy ataków i penetracyjne mogą pomóc w zidentyfikowaniu luk w zabezpieczeniach w interfejsach oprogramowania. Aby uzyskać więcej informacji, zobacz Testy Penetracyjne (Podstawy Urządzeń).

Użyj Device Guard — test zgodności, wraz z innymi narzędziami opisanymi w tym artykule, aby potwierdzić, że sterownik jest zgodny z standardem HVCI.

Niestandardowe i specyficzne dla domeny narzędzia testowe

Rozważ opracowanie niestandardowych testów zabezpieczeń specyficznych dla domeny. Aby opracować dodatkowe testy, zbierz dane wejściowe od oryginalnych projektantów oprogramowania oraz niezwiązane z projektem zasoby programistyczne zaznajomione z opracowywanym konkretnym typem sterownika, a także jedną lub więcej osób zaznajomionych z analizą i zapobieganiem włamaniom.

Jak zgłaszać podatne i złośliwe sterowniki za pomocą Centrum zgłaszania podatnych i złośliwych sterowników firmy Microsoft.

element listy kontrolnej zabezpieczeń nr 18: Informacje o tym, jak sterowniki są zgłaszane przy użyciu Centrum raportowania czynników narażonych na zagrożenia firmy Microsoft i złośliwego sterownika

Każdy może zgłosić wątpliwy sterownik za pomocą Centrum zgłaszania podatnych i złośliwych sterowników firmy Microsoft. Zapoznaj się z tym wpisem w blogu, aby uzyskać informacje na temat sposobu przesyłania sterowników do analizy — Ulepszanie zabezpieczeń jądra za pomocą nowego centrum raportowania czynników narażonych i złośliwych sterowników firmy Microsoft

Centrum raportowania może skanować i analizować sterowniki systemu Windows utworzone pod kątem architektur x86 i x64. Wrażliwe i złośliwe zeskanowane sterowniki są oflagowane do analizy i zbadania przez zespół ds. sterowników podatnych na zagrożenia firmy Microsoft. Po potwierdzeniu kierowców podatnych na zagrożenia następuje odpowiednie powiadomienie, a następnie zostają oni dodani do listy blokowanych kierowców. Aby uzyskać więcej informacji na ten temat, zobacz Zalecane reguły blokowania sterowników firmy Microsoft. Te reguły są domyślnie stosowane do urządzeń z włączoną integralnością kodu chronionego przez funkcję Hypervisor (HVCI) i systemu Windows 10 w trybie S.

Przeglądanie bezpiecznych zasobów kodowania

element listy kontrolnej zabezpieczeń nr 19:Przejrzyj te zasoby, aby rozwinąć zrozumienie najlepszych rozwiązań dotyczących bezpiecznego kodowania, które mają zastosowanie do deweloperów sterowników.

Wskazówki dotyczące kodowania sterowników w bezpiecznym trybie jądra

tworzenie niezawodnych sterowników Kernel-Mode

Organizacje ds. bezpiecznego kodowania

Carnegie Mellon University SEI CERT

Carnegie Mellon University SEI CERT C Coding Standard: Reguły tworzenia bezpiecznych, niezawodnych i bezpiecznych systemów (wersja 2016).

MITRE — słabości rozwiązane przez standard bezpiecznego kodowania CERT C

Tworzenie modelu zabezpieczeń w dojrzałości (BSIMM) — https://www.bsimm.com/

SAFECode — https://safecode.org/

Zasoby CISA

OSR

OSR zapewnia szkolenia i usługi doradcze w zakresie rozwoju sterowników. Te artykuły z biuletynu OSR podkreślają kwestie bezpieczeństwa sterowników.

Nazwy, deskryptory zabezpieczeń i klasy urządzeń — udostępnianie obiektów urządzeń... i bezpieczne

Musisz korzystać z ochrony — zabezpieczenia wewnętrzne sterownika urządzenia &

blokowanie sterowników — ankieta dotycząca technik

Meltdown i Spectre: Co z sterownikami?

Studium przypadku

Od alertu do podatności sterownika: badanie w usłudze Microsoft Defender ATP ujawnia lukę w eskalacji uprawnień

Książki

24 śmiertelnych grzechów zabezpieczeń oprogramowania: wady programistyczne i jak je naprawić przez Michaela Howarda, Davida LeBlanca i Johna Viega

Sztuka oceny zabezpieczeń oprogramowania: identyfikowanie i zapobieganie lukom w zabezpieczeniach oprogramowania, Mark Dowd, John McDonald i Justin Schuh

Pisanie Bezpiecznego Oprogramowania, Drugie Wydanie, Michael Howard i David LeBlanc

The Art of Software Security Assessment: Identyfikowanie i zapobieganie lukom w zabezpieczeniach oprogramowania, Mark Dowd i John McDonald

Bezpieczne Programowanie w C i C++ (Seria SEI w Inżynierii Oprogramowania) 2. wydanie, Robert C. Seacord

Programowanie modelu sterowników systemu Microsoft Windows (2.nd Edition), Walter Oney

tworzenie sterowników za pomocą programu Windows Driver Foundation (dokumentacja dla deweloperów), Penny Orwick i Guy Smith

Szkolenie

Szkolenie na potrzeby zajęć sterowników systemu Windows jest dostępne od dostawców, takich jak:

Bezpieczne trenowanie kodu online jest dostępne z różnych źródeł. Na przykład ten kurs jest dostępny w witrynie coursera:

Identyfikowanie luk w zabezpieczeniach w programowaniu C/C++.

Program SAFECode oferuje również bezpłatne szkolenia:

SAFECode.org/training

Certyfikacja profesjonalna

CERT oferuje certyfikat profesjonalisty z zakresu bezpiecznego kodowania .

Podsumowanie kluczowych wniosków

Bezpieczeństwo kierowców to złożone przedsięwzięcie zawierające wiele elementów, ale oto kilka kluczowych kwestii, które należy wziąć pod uwagę:

  • Sterowniki działają w jądrze systemu Windows, a wystąpienie problemu podczas działania w jądrze naraża cały system operacyjny na ryzyko. W związku z tym należy zwrócić szczególną uwagę na bezpieczeństwo kierowcy i projektowanie z myślą o bezpieczeństwie.

  • Zastosuj zasadę najniższych uprawnień:

    a. Używanie ścisłego ciągu SDDL w celu ograniczenia dostępu do sterownika

    b. Dalsze zaostrzenie ograniczeń dla poszczególnych IOCTL

  • Utwórz model zagrożeń, aby zidentyfikować wektory ataków i rozważyć, czy wszystko może być jeszcze bardziej ograniczone.

  • Należy zachować ostrożność w odniesieniu do wskaźników osadzonych przekazywanych z trybu użytkownika. Muszą one być sprawdzane, dostępne w ramach instrukcji try-except i są podatne na problemy związane z czasem sprawdzania i czasem użycia (ToCToU), chyba że wartość buforu zostanie przechwycona i porównana.

  • Jeśli nie masz pewności, użyj METHOD_BUFFERED jako metody buforowania IOCTL.

  • Użyj narzędzi do skanowania kodu, aby wyszukać znane luki w zabezpieczeniach kodu i rozwiązać wszelkie zidentyfikowane problemy.

  • Poszukaj wiedzy recenzentów kodu, aby wyszukać problemy, które mogły zostać pominięte.

  • Użyj weryfikatorów sterowników i przetestuj sterownik przy użyciu wielu danych wejściowych, w tym przypadków narożnych.