Dela via


Checklista för förares säkerhet

Den här artikeln innehåller en checklista för drivrutinssäkerhet för förarutvecklare för att minska risken för att drivrutiner komprometteras. Drivrutinssäkerheten är kritisk och påverkar tillförlitligheten direkt. När Windows upptäcker att felaktig minnesåtkomst sker stängs operativsystemet av och en blå felskärm visas. Som Windows-partner måste du arbeta för att minska den betydande inverkan som en misslyckad drivrutin har på våra kunders liv.

Mer information om fördelarna med att tillhandahålla en säker och tillförlitlig drivrutin finns i Vägledning för drivrutinssäkerhet.

Översikt över drivrutinssäkerhet

En säkerhetsbrist är ett fel som gör att en angripare kan orsaka att en drivrutin fungerar dåligt på ett sådant sätt att en angripare kan få obehörig åtkomst, manipulera systemet eller kompromettera data, vilket kan leda till att systemet kraschar eller blir oanvändbart. Dessutom kan säkerhetsrisker i drivrutinskoden göra det möjligt för en angripare att få åtkomst till kerneln, vilket skapar en möjlighet att äventyra hela operativsystemet.

När de flesta utvecklare arbetar med sin drivrutin fokuserar de på att få drivrutinen att fungera korrekt och inte på om en angripare försöker utnyttja sårbarheter i sin kod. När en drivrutin har släppts kan dock angripare försöka avsöka och identifiera säkerhetsbrister. Utvecklare måste överväga dessa problem under design- och implementeringsfasen för att minimera sannolikheten för sådana sårbarheter. Målet är att eliminera alla kända säkerhetsfel innan drivrutinen släpps.

För att skapa säkrare drivrutiner krävs samarbete mellan systemarkitekten (tänk medvetet på potentiella hot mot drivrutinen), utvecklaren som implementerar koden (defensivt kodar vanliga åtgärder som kan vara källan till sårbarheter) och testteamet (försöker proaktivt hitta svaghet och sårbarheter). Genom att samordna alla dessa aktiviteter på ett korrekt sätt förbättras säkerheten för föraren dramatiskt.

Förutom att undvika problem med att en drivrutin attackeras ökar många av de steg som beskrivs, till exempel mer exakt användning av kernelminne, drivrutinens tillförlitlighet. Detta minskar supportkostnaderna och ökar kundnöjdheten med din produkt. Genom att slutföra uppgifterna i checklistan nedan kan du uppnå alla dessa mål.

Säkerhetschecklista:Slutför säkerhetsuppgiften som beskrivs i vart och ett av dessa avsnitt.

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Bekräfta att en kerneldrivrutin krävs

Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Använd drivrutinsramverken

Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Hantera åtkomstkontroll för förare

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Kontrollera åtkomsten till drivrutiner endast för programvara

Obockad kryssruta som representerar ett objekt i säkerhetschecklistan. Följ riktlinjerna för säker kodning av drivrutiner

kryssrutan Omarkerad som representerar ett objekt i säkerhetschecklistan. Implementera HVCI-kompatibel kod

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Följ bästa praxis för teknikspecifik kod

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Lägg till SAL-kommentarer i drivrutinskoden

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Utföra peer-granskning av kod

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Utför hotanalys

Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Använd CodeQL för att kontrollera drivrutinskoden

kryssrutan omarkerad som representerar ett objekt i säkerhetschecklistan. Använd Verifieraren för drivrutiner för att hitta sårbarheter

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Kontrollera kod med program för maskinvarukompatibilitetstester

sv-SE: Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan.Kontrollera att du är redo att skicka drivrutiner med verktyg som BinSkim och SignTool

Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Signera inte testdrivrutinskod i produktion

Omarkerad kryssruta som representerar ett föremål i säkerhetschecklistan. Kör korrekt signering av drivrutinens version och distribuera ditt drivrutinspaket med Windows Update

omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Lär dig hur drivrutiner rapporteras via Microsoft Vulnerable and Malicious Driver Reporting Center

Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Granska säkra kodningsresurser

Omarkerad kryssruta som representerar ett objekt i säkerhetschecklistan. Granska Sammanfattningen av de viktiga slutsatserna

Bekräfta att en kerneldrivrutin krävs

Säkerhetschecklista nr 1:Bekräfta att en kerneldrivrutin krävs och att en metod med lägre risk, till exempel Windows-tjänsten eller appen, inte är ett bättre alternativ.

Kerneldrivrutiner finns i Windows-kerneln och har ett problem när du kör i kerneln exponerar hela operativsystemet. Om något annat alternativ är tillgängligt blir det sannolikt lägre kostnad och har mindre associerad risk än att skapa en ny kerneldrivrutin.

Mer information om hur du använder de inbyggda Windows-drivrutinerna finns i Behöver du skriva en drivrutin?.

Information om hur du använder bakgrundsaktiviteter finns i Stötta din app med bakgrundsaktiviteter.

Information om hur du använder Windows-tjänster finns i Services.

Använda drivrutinsramverken

säkerhetschecklista nr 2:Använd drivrutinsramverken för att minska kodens storlek och öka dess tillförlitlighet och säkerhet.

Använd Windows Driver Frameworks för att minska kodens storlek och öka dess tillförlitlighet och säkerhet. Kom igång genom att läsa Använda WDF för att utveckla en drivrutin. Information om hur du använder UMDF (User Mode Driver Framework) med lägre risk finns i Välja en drivrutinsmodell.

Att skriva en gammaldags Windows Driver Model (WDM) drivrutin är mer tidskrävande, kostsamt och innebär att återskapa kod som är tillgänglig i drivrutinsramverken.

WDF-källkoden (Windows Driver Framework) är öppen källkod och tillgänglig på GitHub. Det här är samma WDF-källkod som levereras i Windows. Du kan felsöka drivrutinen mer effektivt när du kan följa interaktionerna mellan drivrutinen och WDF. Ladda ned den från https://github.com/Microsoft/Windows-Driver-Frameworks.

DMF – Drivmodulramverk

Överväg att använda Driver Module Framework (DMF) i drivrutinsprojektet. DMF är utvecklat av Microsoft Surface-teamet och är ett ramverk som gör det möjligt att skapa WDF-objekt som kallas DMF-moduler. Koden för dessa DMF-moduler kan delas mellan olika drivrutiner. Dessutom tillhandahåller DMF ett bibliotek med DMF-moduler som har utvecklats för drivrutiner och erbjuder återanvändning av kod för uppgifter som tråd- och I/O-hantering. En DMF-modul används för att kapsla in drivrutinsaktiviteter i mindre enheter. Varje modul är fristående och har egen kod, kontext och återanrop, vilket gör det enklare att återanvända. Mer information finns i Introducing Driver Module Framework and the GitHub site documentation.

Hantera åtkomstkontroll för förare

säkerhetschecklista nr 3:Granska din drivrutin för att kontrollera att du kontrollerar åtkomsten korrekt.

Hantera åtkomstkontroll för drivrutiner – WDF

Drivrutiner måste fungera för att förhindra att användare får olämplig åtkomst till en dators enheter och filer. För att förhindra obehörig åtkomst till enheter och filer måste du:

  • Namnge endast enhetsobjekt när det behövs. Namngivna enhetsobjekt är vanligtvis bara nödvändiga av äldre skäl, till exempel om du har ett program som förväntar sig att öppna enheten med ett visst namn eller om du använder en enhet/kontrollenhet som inte är PNP. WDF-drivrutiner behöver inte namnge sin PnP-enhets-FDO för att skapa en symbolisk länk med hjälp av WdfDeviceCreateSymbolicLink.

  • Säker åtkomst till enhetsobjekt och gränssnitt.

För att tillåta att program eller andra WDF-drivrutiner får åtkomst till PnP-enhetens PDO bör du använda enhetsgränssnitt. Mer information finns i Använda enhetsgränssnitt. Ett enhetsgränssnitt fungerar som en symbolisk länk till enhetsstackens PDO.

Ett av de bättre sätten att styra åtkomsten till PDO är genom att ange en SDDL-sträng i INF. Om SDDL-strängen inte finns i INF-filen använder Windows en standardsäkerhetsbeskrivning. Mer information finns i Skydda enhetsobjekt och SDDL för enhetsobjekt.

Mer information om hur du kontrollerar åtkomst finns i:

styra enhetsåtkomst i KMDF-drivrutiner

Namn, säkerhetsbeskrivningar och enhetsklasser – gör enhetsobjekt tillgängliga... och SAFE från januari februari 2017 NT Insider Newsletter utgiven av OSR.

Hantera åtkomstkontroll för drivrutiner – WDM

Om du arbetar med en WDM-drivrutin och du använde ett namngivet enhetsobjekt kan du använda IoCreateDeviceSecure och ange en SDDL för att skydda den. När du implementerar IoCreateDeviceSecure ska du alltid ange ett anpassat klass GUID för DeviceClassGuid. Du bör inte ange ett befintligt klass-GUID här. Om du gör det kan säkerhetsinställningar eller kompatibilitet brytas för andra enheter som tillhör den klassen. Mer information finns i WdmlibIoCreateDeviceSecure.

Mer information finns i:

Kontroll av enhetsåtkomst

Styra åtkomst till enhetsnamnområde

Windows-säkerhetsmodell för drivrutinsutvecklare

Riskhierarki för säkerhetsidentifierare (SID)

I följande avsnitt beskrivs riskhierarkin för vanliga SID:er som används i drivrutinskoden. Allmän information om SDDL finns i SDDL för enhetsobjekt, SID-strängaroch SDDL-strängsyntax.

Det är viktigt att förstå att om anropare med lägre behörighet får åtkomst till kerneln ökar kodrisken. I det här sammanfattningsdiagrammet ökar risken eftersom du tillåter sid-åtkomst med lägre behörighet till din drivrutinsfunktion.

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

Enligt den allmänna säkerhetsprincipen för lägsta behörighet konfigurerar du endast den lägsta åtkomstnivå som krävs för att drivrutinen ska fungera.

WDM Finfördelad IOCTL-säkerhetskontroll

En IOCTL (Input/Output Control) i Windows är ett systemanrop för enhetsspecifika in- och utdataåtgärder. IOCTL:er används av program för att kommunicera med enhetsdrivrutiner, så att de kan skicka kommandon eller begära information från maskinvaran. Mer information finns i Introduktion till I/O-kontrollkoder och Exempel på I/O-begäran – En översikt.

Om du vill hantera säkerheten ytterligare när IOCTLs skickas av anropare i användarläge kan drivrutinskoden innehålla funktionen IoValidateDeviceIoControlAccess. Med den här funktionen kan en förare kontrollera åtkomsträttigheter. När en IOCTL tas emot kan en drivrutin anropa IoValidateDeviceIoControlAccessoch ange FILE_READ_ACCESS, FILE_WRITE_ACCESS eller båda.

Att implementera detaljerad IOCTL-säkerhetskontroll ersätter inte behovet av att hantera drivrutinsåtkomst med hjälp av de tekniker som beskrivs ovan.

Mer information finns i Definiera I/O-kontrollkoder och säkerhetsproblem för I/O-kontrollkoder.

Kontrollera åtkomsten till drivrutiner endast för programvara

Säkerhetschecklista nr 4:Om en drivrutin endast för programvara ska skapas måste ytterligare åtkomstkontroll implementeras.

Kerneldrivrutiner med endast programvara använder inte plug-and-play (PnP) för att associeras med specifika maskinvaru-ID:er och kan köras på valfri dator. En sådan drivrutin kan användas för andra syften än den som ursprungligen var avsedd, vilket skapar en attackvektor.

Eftersom kerneldrivrutiner endast för programvara innehåller ytterligare risker måste de begränsas till att köras på specifik maskinvara, till exempel genom att använda ett unikt PnP-ID för att aktivera skapandet av en PnP-drivrutin, eller genom att kontrollera SMBIOS-tabellen för förekomsten av specifik maskinvara.

Anta till exempel att OEM Fabrikam vill distribuera en drivrutin som möjliggör ett överklockningsverktyg för sina system. Om den här drivrutinen, som är endast programvara, skulle köras på ett system från en annan originalutrustningstillverkare (OEM) kan systeminstabilitet eller skada uppstå. Fabrikams system bör innehålla ett unikt PnP-ID för att göra det möjligt att skapa en PnP-drivrutin som också är uppdaterbar via Windows Update. Om detta inte är möjligt, och Fabrikam skapar en äldre drivrutin, bör drivrutinen hitta en annan metod för att kontrollera att den körs på ett Fabrikam-system, till exempel genom att undersöka SMBIOS-tabellen innan du aktiverar några funktioner.

Följ riktlinjerna för säker kodning av drivrutiner

Säkerhetschecklista nr 5:Granska koden och ta bort eventuella kända kodsårbarheter.

Kärnaktiviteten med att skapa säkra drivrutiner är att identifiera områden i koden som behöver ändras för att undvika kända sårbarheter i programvaran. Många av dessa kända programvarusårbarheter handlar om att hålla strikt koll på minnesanvändningen för att undvika problem med att andra skriver över eller på annat sätt äventyrar de minnesplatser som din drivrutin använder.

Kodgenomsökningsverktyg som CodeQL och drivrutinsspecifika tester kan användas för att hitta, vissa, men inte alla, av dessa säkerhetsrisker. Dessa verktyg och tester beskrivs senare i det här avsnittet.

Minnesbuffertar

Använd lämplig metod för att komma åt databuffertar med IOCTLs

Ett av de primära ansvarsområdena för en Windows-drivrutin är att överföra data mellan program i användarläge och ett systems enheter. De tre metoderna för att komma åt databuffertar visas i följande tabell.

IOCTL-bufferttyp Sammanfattning Mer information
METHOD_BUFFERED Rekommenderas för de flesta situationer med buffrad I/O-
METHOD_IN_DIRECT eller METHOD_OUT_DIRECT Används i viss höghastighets-I/O-maskinvara. Användning av direkt I/O
METHOD_NEITHER Undvik om möjligt Använder varken buffrad eller direkt I/O

I allmänhet rekommenderas buffrad I/O eftersom den tillhandahåller de säkraste buffringsmetoderna. Men även när du använder buffrad I/O finns det risker, till exempel inbäddade pekare som måste minimeras.

Mer information om hur du arbetar med buffertar i IOCTLs finns i Metoder för åtkomst till databuffertar.

Fel vid användning av IOCTL-buffrad I/O

  • Kontrollera storleken på IOCTL-relaterade buffertar. Mer information finns i Det gick inte att kontrollera storleken på buffertar.

  • Initiera utdatabuffertar korrekt. Mer information finns i Det gick inte att initiera utdatabuffertar.

  • Verifiera buffertar med variabel längd korrekt. För mer information, se Misslyckades med att validera Variable-Length buffertar.

  • När du använder buffrad I/O måste du se till och returnera rätt längd för OutputBuffer i fältet IO_STATUS_BLOCK strukturinformation. Returnera inte bara längden direkt från en READ-begäran. Tänk dig till exempel en situation där returnerade data från användarutrymmet anger att det finns en 4K-buffert. Om drivrutinen faktiskt bara ska returnera 200 byte, men i stället bara returnerar 4K i fältet Information, har en säkerhetsrisk för informationsupplysning inträffat. Det här problemet beror på att bufferten som I/O-hanteraren använder för buffrad I/O inte nollställs i tidigare versioner av Windows. Därför får användarappen tillbaka de ursprungliga 200 bytena med data plus 4K-200 byte av vad som fanns i bufferten (icke-sidat poolinnehåll). Det här scenariot kan inträffa med all användning av buffrad I/O och inte bara med IOCTLs.

Fel i IOCTL-direkt-I/O

Hantera buffertar med noll längd korrekt. Mer information finns i -fel i Direct I/O.

Fel vid hänvisning till adresser för användarutrymme

Drivrutinskoden måste använda minnet korrekt

  • Alla tilldelningar av drivrutinspooler måste finnas i en icke-körbar pool (NX). Att använda NX-minnespooler är i sig säkrare än att använda körbara icke-sidiga pooler (NP) och ger bättre skydd mot spillattacker.

  • För att tillåta att drivrutiner stöder HVCI-virtualisering finns det ytterligare minneskrav. Mer information finns i Implementera HVCI-kompatibel kod senare i den här artikeln.

TOCTOU-sårbarheter

Det finns en potentiell tid för kontroll till tidpunkt för användning (TOCTOU) sårbarhet när du använder direkt I/O (för IOCTLs eller för Läs/skriv). Tänk på att eftersom drivrutinen har åtkomst till användardatabufferten kan användarappen samtidigt komma åt samma databuffert.

För att hantera den här risken kopierar du alla parametrar som måste verifieras från användardatabufferten till minne som endast är tillgängligt från kernelläge, till exempel stacken eller poolen. När data inte kan nås av användarprogrammet verifierar och använder du sedan de data som skickades in.

MSR-modellspecifika registerläsningar och skrivningar

Kompilatorns inbyggda egenskaper, till exempel __readmsr och __writemsr kan användas för att komma åt modellspecifika register. Om den här åtkomsten krävs måste drivrutinen alltid kontrollera att registret att läsa eller skriva till är begränsat till det förväntade indexet eller intervallet.

Mer information och kodexempel finns i Ge möjlighet att läsa/skriva MSR:er i Metodtips för att begränsa högprivilegierat beteende i kernellägesdrivrutiner.

Handtag

Enhetsobjekt

IRP:er

IRP:er (Windows I/O Request Packets) används för att kommunicera I/O-begäranden mellan operativsystemet och drivrutiner i kernelläge, vilket kapslar in all nödvändig information i paketet. IP-adresser underlättar asynkron dataöverföring, synkronisering och felhantering, vilket säkerställer effektiv och tillförlitlig kommunikation med maskinvaruenheter. Mer information finns i I/O Request Packets and Overview of the Windows I/O Model.

WDF och IRP:er

En fördel med att använda WDF är att WDF-drivrutiner vanligtvis inte har direkt åtkomst till IP-adresser. Ramverket konverterar till exempel de WDM-IRP:er som representerar läs-, skriv- och enhets-I/O-kontrollåtgärder till ramverksbegärandeobjekt som KMDF/UMDF tar emot i I/O-köer. När det är möjligt rekommenderar vi starkt att du använder WDF.

Om du behöver skriva en WDM-drivrutin läser du följande vägledning.

Hantera IRP I/O-buffertar korrekt

Granska de här avsnitten som beskriver hur du verifierar IRP-indatavärden:

DispatchReadWrite med buffrad I/O-

Fel i buffrad in-/utmatning

DispatchReadWrite med direkt I/O

Fel i direkt I/O

Verifiera värden som är associerade med en IRP, till exempel buffertadresser och längder.

Om du väljer att använda Neither I/O IOCTL, bör du vara medveten om att, till skillnad från Läs och Skriv, samt till skillnad från Buffrad I/O och Direkt I/O, verifieras inte buffertpekarna och längderna av I/O-hanteraren.

Hantera IRP-slutförandeåtgärder korrekt

En drivrutin får aldrig slutföra en IRP med statusvärdet STATUS_SUCCESS om den inte faktiskt stöder och bearbetar IRP. Information om rätt sätt att hantera IRP-slutförandeåtgärder finns i Slutföra IRP:er.

Hantera drivrutins-IRP i vänteläge

Drivrutinen bör indikera att IRP väntar innan den sparar IRP, och bör överväga att inkludera både anropet till IoMarkIrpPending och tilldelningen i en interlockad sekvens. Mer information finns i det gick inte att kontrollera drivrutinstillståndet och att hålla inkommande IP-adresser när en enhet pausas.

Hantera IRP-annulleringsåtgärder korrekt

Avbryt åtgärder kan vara svåra att koda korrekt eftersom de vanligtvis körs asynkront. Problem i koden som hanterar avbrutna åtgärder kan gå obemärkt förbi under lång tid, eftersom den här koden vanligtvis inte körs ofta i ett system som körs. Var noga med att läsa och förstå all information som ges under Avbrytande av IRP:er. Var särskilt uppmärksam på Synkronisering av IRP-anullering och Att Tänka På När du Avbryter IRP:er.

Ett rekommenderat sätt att minimera synkroniseringsproblemen som är associerade med avbrutna åtgärder är att implementera en avbruten IRP-kö.

Hantera IRP-rensning och stängningsoperationer korrekt

Se till att du förstår skillnaden mellan IRP_MJ_CLEANUP och IRP_MJ_CLOSE begäranden. Rensningsbegäranden tas emot när ett program stänger alla referenser på ett filobjekt, men ibland innan alla I/O-begäranden har slutförts. Stängningsbegäranden anländer efter att alla I/O-begäranden för filobjektet har slutförts eller avbrutits. Mer information finns i följande:

DispatchCreate, DispatchClose och DispatchCreateClose-rutiner

DispatchCleanup rutiner

fel vid hantering av rensnings- och stängningsåtgärder

Mer information om hur du hanterar IRP:er på rätt sätt finns i Ytterligare fel vid hantering av IRP:er.

Använda säkra funktioner

Andra säkerhetsproblem

  • Använd ett lås eller en sammanflätad sekvens för att förhindra konkurrensförhållanden. Mer information finns i Fel i en miljö med flera processorer.

  • Se till att inga TDI-filter (Network Transport Driver Interface) eller Layered Service Providers (LSP: er) installeras av drivrutinen eller tillhörande programvarupaket under installationen eller användningen. Använd i stället moderna API:er, till exempel Windows Filtering Platform (WFP) .

Ytterligare kodsårbarheter

Förutom de eventuella säkerhetsrisker som beskrivs här innehåller den här artikeln ytterligare information om hur du förbättrar säkerheten för drivrutinskoden i kernelläge: Skapa tillförlitliga Kernel-Mode-drivrutiner.

Mer information om säker C- och C++-kodning finns i Säkra kodningsresurser i slutet av den här artikeln.

Implementera HVCI-kompatibel kod

Säkerhetschecklista nr 6:Verifiera att drivrutinen använder minne så att den är HVCI-kompatibel.

Minnesintegritet och HVCI-kompatibilitet

Minnesintegritet, även kallat Hypervisor-skyddad kodintegritet (HVCI) använder maskinvaruteknik och virtualisering för att isolera beslutsfunktionen kodintegritet (CI) från resten av operativsystemet. När du använder virtualiseringsbaserad säkerhet för att isolera CI är det enda sättet att köra kernelminnet genom en CI-verifiering. Det innebär att kernelminnessidor aldrig kan vara skrivbara och körbara (W+X) och att körbar kod inte kan ändras direkt.

Om du vill implementera HVCI-kompatibel kod kontrollerar du att drivrutinskoden gör följande:

  • Väljer NX som standard
  • Använder NX-API:er/flaggor för minnesallokering (NonPagedPoolNx)
  • Använder inte avsnitt som är både skrivbara och körbara
  • Försöker inte ändra körbart systemminne direkt
  • Använder inte dynamisk kod i kernel
  • Läser inte in datafiler som körbara filer
  • Avsnittsjustering är en multipel av 0x1000 (PAGE_SIZE). Till exempel DRIVER_ALIGNMENT=0x1000

Mer information om hur du använder verktyget och en lista över inkompatibla minnesanrop finns i Implementera HVCI-kompatibel kod.

Mer information om det relaterade säkerhetstestet för grunderna i systemet finns i HyperVisor Code Integrity Readiness Test and Hypervisor-Protected Code Integrity (HVCI).

Förbättra säkerheten för enhetsinstallation

Säkerhetschecklista nr 7:Granska vägledningen för skapande och installation av inf-drivrutiner för att se till att du följer de bästa metoderna.

När du skapar koden som installerar drivrutinspaketet måste du se till att installationen av enheten alltid utförs på ett säkert sätt. En säker enhetsinstallation är en som gör följande:

  • Begränsar åtkomsten till enheten och dess enhetsgränssnittsklasser
  • Begränsar åtkomsten till de drivrutinstjänster som skapades för enheten
  • Skyddar drivrutinsfiler från ändring eller borttagning
  • Begränsar åtkomsten till enhetens registerposter
  • Begränsar åtkomsten till enhetens WMI-klasser
  • Använder SetupAPI-funktioner korrekt

Mer information finns i följande:

Skapa säkra enhetsinstallationer

riktlinjer för att använda SetupAPI-

Använda enhetsinstallationsfunktioner

Avancerade avsnitt om installation av enhet och drivrutin

Följ metodtips för teknikspecifik kod

Säkerhetschecklista nr 8:Granska följande teknikspecifika vägledning för din drivrutin.

Filsystem

Mer information om säkerhet för filsystemdrivrutiner finns i följande:

Introduktion till filsystemsäkerhet

Säkerhetsproblem i filsystemet

säkerhetsfunktioner för filsystem

samexistens med andra filsystemfilterdrivrutiner

Microsoft Virus Initiative

Microsoft Virus Initiative (MVI) hjälper organisationer att förbättra de säkerhetslösningar som våra kunder förlitar sig på för att skydda dem. Microsoft tillhandahåller verktyg, resurser och kunskap för att stödja bättre tillsammans upplevelser med bra prestanda, tillförlitlighet och kompatibilitet. Microsoft samarbetar med MVI-partner för att definiera och följa SDP (Safe Deployment Practices) för att stödja säkerheten och motståndskraften hos våra ömsesidiga kunder.

Om du är antivirusleverantör kan du läsa Microsoft Virus Initiative för att lära dig hur du ansluter till MVI för mer hjälp med programdistribution. Information om hur säkerhetsleverantörer bättre kan utnyttja de integrerade säkerhetsfunktionerna i Windows för ökad säkerhet och tillförlitlighet finns i bästa praxis för Windows-säkerhet för integrering och hantering av säkerhetsverktyg.

NDIS – Nätverk

Information om NDIS-drivrutinssäkerhet finns i säkerhetsproblem för nätverksdrivrutiner.

Skrivare

Information om säkerhet för skrivardrivrutiner finns i säkerhetsöverväganden för V4-skrivardrivrutin.

Säkerhetsproblem för WIA-drivrutiner (Windows Image Acquisition)

Information om WIA-säkerhet finns i säkerhetsproblem för WIA-drivrutiner (Windows Image Acquisition).

Lägga till SAL-anteckningar i drivrutinskoden

Säkerhetschecklista nr 9:Lägg till SAL-anteckningar i drivrutinskoden.

Källkodsanteckningsspråket (SAL) innehåller en uppsättning anteckningar som du kan använda för att beskriva hur en funktion använder sina parametrar, de antaganden som den gör om dem och de garantier som den gör när den är klar. Anteckningarna definieras i huvudfilen sal.h. Visual Studio-kodanalys för C++ använder SAL-anteckningar för att ändra dess analys av funktioner. Mer information om utveckling av SAL 2.0 för Windows-drivrutiner finns i SAL 2.0-anvisningar för Windows-drivrutiner och Använda SAL-anvisningar för att minska C/C++-kodfel.

Allmän information om SAL finns i den här artikeln som är tillgänglig från OSR. SAL-anteckningar: Hata mig inte för att jag är vacker

Genomföra kollega-kodgranskning

Säkerhetschecklista nr 10:Utföra peer-kodgranskning för att söka efter problem som inte visas av de andra verktygen och processerna

Sök efter kunniga kodgranskare för att leta efter problem som du kanske har missat. En andra uppsättning ögon ser ofta problem som du kanske har förbisett.

Om du inte har lämplig personal för att granska din kod internt kan du överväga att kontakta hjälp utifrån för detta ändamål.

Utföra hotanalys

Säkerhetschecklista nr 11:Antingen ändrar du en befintlig modell för drivrutinshot eller skapar en anpassad hotmodell för drivrutinen.

När det gäller säkerhet är en vanlig metod att skapa specifika hotmodeller som försöker beskriva de typer av attacker som är möjliga. Den här tekniken är användbar när du utformar en drivrutin eftersom den tvingar utvecklaren att överväga potentiella attackvektorer mot en drivrutin i förväg. Efter att ha identifierat potentiella hot kan en förarutvecklare sedan överväga sätt att försvara sig mot dessa hot för att stärka den övergripande säkerheten för drivrutinskomponenten.

Den här artikeln innehåller drivrutinsspecifik vägledning för att skapa en lätt hotmodell: Hotmodellering för drivrutiner. Artikeln innehåller ett exempel på modelldiagram för drivrutinshot som kan användas som startpunkt för din drivrutin.

Exempeldataflödesdiagram som illustrerar en hypotetisk drivrutin i kernelläge.

Metodtips och tillhörande verktyg för säkerhetsutvecklingslivscykel (SDL) kan användas av IHV:er och OEM-tillverkare för att förbättra säkerheten för deras produkter. Mer information finns i SDL-rekommendationer för OEM-tillverkare.

Använd CodeQL för att kontrollera drivrutinskoden

Säkerhetschecklista nr 12:Använd CodeQL för att söka efter säkerhetsrisker i drivrutinskoden.

CodeQL, från GitHub, är en semantisk kodanalysmotor, och kombinationen av en omfattande uppsättning säkerhetsfrågor tillsammans med en robust plattform gör det till ett värdefullt verktyg för att skydda drivrutinskoden. Mer information finns i CodeQL och logotestet för statiska verktyg.

Använd drivrutinsverifierare för att söka efter sårbarheter

Säkerhetschecklista nr 13:Använd drivrutinsverifierare för att söka efter säkerhetsrisker i drivrutinskoden.

Drivrutinsverifieraren använder en uppsättning gränssnittsregler och en modell av operativsystemet för att avgöra om drivrutinen interagerar korrekt med Windows-operativsystemet. Drivrutinsverifieraren hittar fel i drivrutinskoden som kan peka på potentiella buggar i drivrutiner.

Verifierare för drivrutiner möjliggör pågående testning av drivrutinen. Drivrutinsverifieraren övervakar drivrutiner och grafikdrivrutiner i Windows-kernelläge för att identifiera olagliga funktionsanrop eller åtgärder som kan skada systemet. Med ett bifogat felsökningsprogram kan du visa körning av operativsystem och drivrutinskod i realtid. Drivrutinsverifieraren kan utsätta Windows-drivrutinerna för en mängd olika påfrestningar och tester för att hitta felaktigt beteende. Mer information finns i Drivrutinsverifierare.

Driver Verifer fungerar med både WDM- och KMDF-drivrutiner. Mer information om vad den kan kontrollera finns i följande avsnitt.

Mer information om de drivrutiner som drivrutinsverifieraren kan arbeta med finns i DDI Efterlevnadsregler och drivrutiner som stöds. Mer information om ytterligare kontrollantregler för specifika typer av drivrutiner finns i:

Om du vill bekanta dig med DV kan du använda en av exempeldrivrutinerna (till exempel det aktuella brödrostens exempel: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).

Kontrollera koden med testerna för maskinvarukompatibilitetsprogrammet

Säkerhetschecklista nr 14:Använd säkerhetsrelaterade tester av maskinvarukompatibilitetsprogram för att söka efter säkerhetsproblem.

Maskinvarukompatibilitetsprogrammet innehåller säkerhetsrelaterade tester som kan användas för att söka efter kodsårbarheter. Windows Maskinvarukompatibilitetsprogram utnyttjar testerna i Windows Hardware Lab Kit (HLK). HLK Device Fundamentals-test kan användas på kommandoraden för att testa drivrutinskod och identifiera svagheter. Allmän information om de grundläggande enhetstesterna och programmet för maskinvarukompatibilitet finns i Windows Hardware Lab Kit.

Följande tester är exempel på tester som kan vara användbara för att kontrollera drivrutinskoden för vissa beteenden som är associerade med kodsårbarheter:

DF – Fuzz random IOCTL-test (tillförlitlighet)

DF – Fuzz sub-opens test (Tillförlitlighet)

DF – Fuzz-test för buffert med noll längd FSCTL-test (tillförlitlighet)

DF – Fuzz random FSCTL-test (tillförlitlighet)

DF – Fuzz Misc API-test (tillförlitlighet)

Du kan också använda kernelsynkroniseringsfördröjningen för att som ingår i drivrutinsverifieraren.

Chaos-testerna (samtidig maskinvara och operativsystem) kör olika PnP-drivrutinstester, fuzz-tester för enhetsdrivrutiner och kraftsystemtester samtidigt. Mer information finns i CHAOS-tester (enheternas grundläggande funktioner).

Intrångstester för enhetens grundläggande säkerhetsfunktioner utför olika former av inputattacker, som är en viktig komponent i säkerhetstester. Attack- och intrångstestning kan hjälpa dig att identifiera sårbarheter i programvarugränssnitt. Mer information finns i penetrationstester (enhetens grunder).

Använd Device Guard – Efterlevnadstest, tillsammans med de andra verktygen som beskrivs i den här artikeln, för att bekräfta att drivrutinen är HVCI-kompatibel.

Anpassade och domänspecifika testverktyg

Överväg att utveckla anpassade domänspecifika säkerhetstester. För att utveckla ytterligare tester, samla in indata från de ursprungliga designerna av programvaran, samt orelaterade utvecklingsresurser som är bekanta med den specifika typ av drivrutin som utvecklas, och en eller flera personer som är bekanta med analys och förebyggande av säkerhetsintrång.

Kontrollera drivrutiner som är redo för leverans med verktyg som BinSkim och SignTool

Säkerhetschecklista nr 15:Kontrollera kompilerad kod med verktyg som BinSkim och SignTool innan den laddas upp till partnercenter.

Använd verktyg som BinSkim och SignTool för att undersöka binära filer för att kontrollera kompilerad kod innan den laddas upp till partnercentret som ska distribueras med Windows Update. Att ha verktyg på plats för att kontrollera kompilerade binärfiler, innan de skickas för distribution, lägger till i ett annat skyddslager.

BinSkim

BinSkim kan identifiera kodnings- och byggmetoder som potentiellt kan göra binärfilen sårbar. BinSkim söker efter:

  • Användning av inaktuella kompilatorverktygsuppsättningar – Binärfiler bör kompileras mot de senaste kompilatorverktygsuppsättningarna där det är möjligt för att maximera användningen av aktuella säkerhetsreduceringar på kompilatornivå och operativsystem.
  • Osäkra kompileringsinställningar – Binärfiler bör kompileras med de säkraste inställningarna som är möjliga för att aktivera säkerhetsreduceringar som tillhandahålls av operativsystemet, maximera kompilatorfel och rapportering av åtgärdsbara varningar, bland annat.
  • Signeringsproblem – Signerade binärfiler bör signeras med kryptografiskt starka algoritmer.

BinSkim är ett verktyg med öppen källkod och genererar utdatafiler som använder formatet Static Analysis Results Interchange Format (SARIF). BinSkim ersätter det tidigare verktyget BinScope.

Mer information om BinSkim finns i Använda BinSkim för att kontrollera binärfiler och BinSkim-användarhandboken.

SignTool

Använd SignTool för att kontrollera versionssignerade drivrutinsfiler. Mer information finns i Verifiera signaturen för en Release-Signed drivrutinsfil och Verifiera signaturen för en katalogfil signerad av ett kommersiellt versionscertifikat.

Signera inte testkod för användning i produktion

Säkerhetschecklista nr 16:Skriv inte ut kod för utveckling, testning och tillverkning av kerneldrivrutinskod för produktion.

Kernel-drivrutinskod som används för utveckling, testning eller tillverkning kan innehålla farliga funktioner som utgör en säkerhetsrisk. Den här farliga koden får aldrig signeras med ett certifikat som är betrott av Windows. Rätt mekanism för att köra farlig drivrutinskod är att inaktivera UEFI Secure Boot, aktivera BCD "TESTSIGNING" och signera koden för utveckling, testning och tillverkning med hjälp av ett ej betrott certifikat (till exempel ett som genereras av makecert.exe).

Kod som har signerats av en betrodd SPC-signatur (Software Publishers Certificate) eller EN WHQL-signatur (Windows Hardware Quality Labs) får inte underlätta förbikoppling av Windows kodintegritet och säkerhetstekniker. Innan koden signeras av en betrodd SPC- eller WHQL-signatur kontrollerar du först att den följer vägledningen från Skapa pålitliga Kernel-Mode Drivrutiner. Dessutom får koden inte innehålla några farliga beteenden, som beskrivs nedan.

Exempel på farligt beteende är följande:

  • Ger möjlighet att mappa godtyckligt kärn-, fysiskt eller enhetsminne till användarläge.
  • Ger möjlighet att läsa eller skriva godtycklig kernel, fysiskt minne eller enhetsminne, inklusive portindata/utdata (I/O).
  • Ger åtkomst till lagring som kringgår Windows-åtkomstkontroll.
  • Ger möjlighet att ändra maskinvara eller inbyggd programvara som drivrutinen inte har utformats för att hantera.

Kör korrekt versionsdrivrutinssignering och distribuera drivrutinspaketet med Hjälp av Windows Update

säkerhetschecklista nr 17:Använd Windows-partnerportalen för att skicka ditt drivrutinspaket som ska signeras och distribueras via Windows Update.

Innan du släpper ett drivrutinspaket till allmänheten skickar du paketet för certifiering. Mer information finns i Test för prestanda och kompatibilitet och Kom igång med maskinvaruprogrammet.

Användning av Windows Update rekommenderas starkt för distribution av drivrutinspaket. Windows Update tillhandahåller ett robust, säkert, globalt skalat och regelkompatibelt distributionssystem som ska användas för att leverera drivrutinsuppdateringar. Mer information finns i Distribuering av ett drivrutinspaket.

Använd gradvis distribution och Driver flighting i Partner Center för Windows Hardware för att distribuera drivrutinspaketet inom definierade Windows Insider-ringar, samtidigt som du tillhandahåller automatisk övervakning och utvärdering. Övervaka distributionen av drivrutinen med hjälp av Microsoft-drivrutinsmått, till exempel Procent av datorer utan krasch i kernelläge för att upprätthålla kvaliteten.

En beskrivning av metoder för säker programvarudistribution finns i CISA-säker programvarudistribution: Hur programvarutillverkare kan säkerställa tillförlitlighet för kunder.

Förstå hur drivrutiner rapporteras med hjälp av Microsoft Vulnerable and Malicious Driver Reporting Center

Säkerhetschecklista nr 18: Förstå hur drivrutiner rapporteras med hjälp av Microsoft Vulnerable and Malicious Driver Reporting Center

Vem som helst kan skicka en tvivelaktig drivrutin med hjälp av Microsoft Vulnerable and Malicious Driver Reporting Center. I den här blogginlägget finns information om hur drivrutiner skickas för analys – Förbättra kernelsäkerheten med nya Microsoft Vulnerable och Malicious Driver Reporting Center

Reporting Center kan skanna och analysera Windows-drivrutiner som skapats för x86- och x64-arkitekturer. Sårbara och skadliga genomsökta drivrutiner flaggas för analys och undersökning av Microsofts sårbara drivrutinsteam. När sårbara drivrutiner har bekräftats, sker en lämplig notifiering och de läggs till i blocklistan för sårbara drivrutiner. Mer information om detta finns i Rekommenderade regler för drivrutinsblockering i Microsoft. Dessa regler tillämpas som standard på HVCI-aktiverade enheter (Hypervisor-skyddad kodintegritet) och Windows 10 i S-läge.

Granska säkra kodningsresurser

Säkerhetschecklista nr 19:Granska dessa resurser för att utöka din förståelse av de metodtips för säker kodning som gäller för drivrutinsutvecklare.

Vägledning för Microsoft NISTIR 8397

Den amerikanska myndighetspublikationen NISTIR 8397: Guidelines on Minimum Standards for Developer Verification of Software by the National Institute of Standards and Technology (NIST) innehåller vägledning om hur man skapar tillförlitlig och säker programvara på alla programmeringsspråk.

Skapa tillförlitliga och säkra C++-program sammanfattar hur du använder Microsofts utvecklarprodukter för C++ och andra språk för att följa NISTIR 8397-riktlinjerna.

NIST-känd säkerhetsriskdatabas för programvara

National Vulnerability Database (NVD) är en sökbar lagringsplats med säkerhetsrelaterade programvarufel, inklusive Windows-drivrutiner.

Sök i NIST sårbarhetsdatabas

översikt över nationella sårbarhetsdatabasen

Säkra kodningsstandarder

Carnegie Mellon University SEI CERT – C Kodningsstandard: Regler för att utveckla säkra, pålitliga och säkra system (PDF).

MITRE – svagheter som hanteras av CERT C Secure Coding Standard

Microsoft Visual Studio – Använda kontrollverktygen för C++ Core Guidelines

Säkra kodningsorganisationer

Cybersecurity and Infrastructure Security Agency (CISA)

CISA-resurser

Carnegie Mellon University SEI CERT

SAFECode

OSR

OSR tillhandahåller utbildning och konsulttjänster för förarutveckling. Dessa artiklar från OSR-nyhetsbrevet belyser problem med drivrutinssäkerhet.

Namn, säkerhetsbeskrivningar och enhetsklasser – gör enhetsobjekt tillgängliga... och SAFE

Du måste använda skydd – Inne i förarhytten & Enhetssäkerhet

Att säkra drivrutiner – En undersökning av tekniker

Meltdown och Spectre: Hur är det med förare?

Fallstudie om sårbarhet för förare

Från avisering till sårbarhet för drivrutin: Microsoft Defender ATP-undersökning avslöjar behörighetseskaleringsfel

Säkerhet i programvaruförsörjningskedjan och programvarufakturering av material (SBOM)

SBOM:er innehåller en lista över ingredienser som används för att skapa en programvara, till exempel programvara med öppen källkod, komponenter och potentiellt även byggverktyg. Detta gör det möjligt för producenter och konsumenter att bättre inventera och utvärdera licens- och sårbarhetsrisker. Microsoft använder SPDX (Software Package Data Exchange) som SBOM-dokumentformat. För mer information, se Generera listor över programvarukomponenter (SBOM) med SPDX på Microsoft och Microsoft tillhandahåller sin verktyg för att generera listor över programvarukomponenter (SBOM) som öppen källkod.

SCITT-initiativet (Integrity, Transparency and Trust) är en uppsättning IETF-internetstandarder för att hantera efterlevnaden av varor och tjänster i leveranskedjor från slutpunkt till slutpunkt. SCITT stöder den pågående verifieringen av varor och tjänster där äktheten hos entiteter, bevis, principer och artefakter kan garanteras och entiteternas åtgärder kan garanteras vara auktoriserade, icke-avvisande, oföränderliga och granskningsbara.

Böcker

24 dödliga synder av programvarusäkerhet: Programmeringsbrister och hur man åtgärdar dem av Michael Howard, David LeBlanc och John Viega

Skriva säker programvara Andra Utgåvan, Michael Howard och David LeBlanc

Konsten att bedöma mjukvarusäkerhet: Identifiering och förebyggande av mjukvarusårbarheter, Mark Dowd, John McDonald och Justin Schuh

Säker kodning i C och C++ (SEI-serien i programvaruteknik) 2:a upplagan, Robert C. Seacord

Programmera Microsoft Windows drivrutinsmodell (2:a upplagan), Walter Oney

Utveckla drivrutiner med Windows Driver Foundation (utvecklarreferens), Penny Orwick och Guy Smith

Träning

Klassrumsutbildning i Windows-drivrutiner erbjuds av leverantörer som följande:

Säker kodning onlineträning är tillgänglig från en mängd olika källor. Den här kursen är till exempel tillgänglig från coursera på:

Identifiera säkerhetsrisker i C/C++-programmering.

SAFECode erbjuder även kostnadsfri utbildning:

SAFECode.org/training

Professionell certifiering

CERT erbjuder en Professionell Certifiering för Säker Kodning.

Sammanfattning av viktiga lärdomar

Förarsäkerhet är en komplex uppgift som innehåller många element, men här är några viktiga punkter att tänka på:

  • Drivrutiner körs i Windows-kärnan, och om ett problem uppstår när de körs i kärnan kan det exponera hela operativsystemet. Därför bör du vara uppmärksam på drivrutinssäkerhet och design med säkerhet i åtanke.

  • Tillämpa principen om lägsta behörighet:

    a. Använda en strikt SDDL-sträng för att begränsa åtkomsten till drivrutinen

    b. Ytterligare begränsa enskilda IOCTL:s

  • Skapa en hotmodell för att identifiera attackvektorer och fundera på om något kan begränsas ytterligare.

  • Var försiktig när det gäller inbäddade pekare som skickas in från usermode. De måste sonderas, nås inom en try-except-sats, och de är benägna att drabbas av problem med tidpunkt för kontroll och användning (ToCToU) om inte buffertens värde samlas in och jämförs.

  • Om du är osäker använder du METHOD_BUFFERED som en IOCTL-buffringsmetod.

  • Använd verktyg för kodgenomsökning, till exempel CodeQL, för att söka efter kända kodsårbarheter och åtgärda eventuella identifierade problem.

  • Sök efter kunniga kodgranskare för att leta efter problem som du kanske har missat.

  • Använd drivrutinsverifierare och testa drivrutinen med flera indata, inklusive gränsfall.