Dela via


Windows-säkerhetsmodell för drivrutinsutvecklare

Windows-säkerhetsmodellen baseras på skyddsbara objekt. Varje komponent i operativsystemet måste säkerställa säkerheten för de objekt som den ansvarar för. Förare måste därför skydda säkerheten för sina enheter och enhetsobjekt.

I det här avsnittet sammanfattas hur Windows-säkerhetsmodellen gäller för drivrutiner i kernelläge.

Windows-säkerhetsmodell

Windows säkerhetsmodell baseras främst på rättigheter per objekt, med ett litet antal systemomfattande privilegier. Objekt som kan skyddas är , men är inte begränsade till, processer, trådar, händelser och andra synkroniseringsobjekt, samt filer, kataloger och enheter.

För varje typ av objekt mappas de generella läs-, skriv- och körbehörigheterna till mer detaljerade, objektspecifika rättigheter. För filer och kataloger omfattar möjliga rättigheter till exempel rätten att läsa eller skriva filen eller katalogen, rätten att läsa eller skriva utökade filattribut, rätten att bläddra i en katalog och rätten att skriva ett objekts säkerhetsbeskrivning.

Säkerhetsmodellen omfattar följande begrepp:

  • Säkerhetsidentifierare (SID)
  • Åtkomsttoken
  • Säkerhetsbeskrivningar
  • Åtkomstkontrollistor (ACLs)
  • Privilegier

Säkerhetsidentifierare (SID)

En säkerhetsidentifierare (SID, även kallat ett huvudnamn) identifierar en användare, en grupp eller en inloggningssession. Varje användare har ett unikt SID som hämtas av operativsystemet vid inloggning.

SID:er utfärdas av en utfärdare, till exempel operativsystemet eller en domänserver. Vissa SID:er är välkända och har både namn och identifierare. SID S-1-1-0 identifierar till exempel Alla (eller Världen).

Åtkomsttoken

Varje process har en åtkomsttoken. Åtkomsttoken beskriver processens fullständiga säkerhetskontext. Den innehåller SID för användaren, SID för de grupper som användaren tillhör och SID för inloggningssessionen samt en lista över de systemomfattande behörigheter som beviljats användaren.

Som standard använder systemet den primära åtkomsttoken för en process när en tråd i processen interagerar med ett skyddsbart objekt. En tråd kan dock personifiera ett klientkonto. När en tråd personifierar har den en personifieringstoken utöver sin egen primära token. Personifieringstoken beskriver säkerhetskontexten för användarkontot som tråden personifierar. Personifiering är särskilt vanligt vid RPC-hantering (Remote Procedure Call).

En åtkomsttoken som beskriver en begränsad säkerhetskontext för en tråd eller process kallas för en begränsad token. SID:erna i en begränsad token kan endast anges för att neka åtkomst, inte tillåta åtkomst, till skyddsbara objekt. Dessutom kan token beskriva en begränsad uppsättning systemomfattande behörigheter. Användarens SID och identitet förblir desamma, men användarens åtkomsträttigheter är begränsade medan processen använder den begränsade token. Funktionen CreateRestrictedToken skapar en begränsad token.

Säkerhetsbeskrivningar

Varje namngivet Windows-objekt har en säkerhetsbeskrivning. vissa namnlösa objekt gör det också. Säkerhetsbeskrivningen beskriver ägare och grupp-SID:er för objektet tillsammans med dess ACL:er.

Ett objekts säkerhetsbeskrivning skapas vanligtvis av funktionen som skapar objektet. När en drivrutin anropar IoCreateDevice eller IoCreateDeviceSecure rutin för att skapa ett enhetsobjekt, tillämpar systemet en säkerhetsbeskrivning på det skapade enhetsobjektet och anger ACL:er för objektet. För de flesta enheter anges ACL:er i inf-filen (device Information).

Mer information om säkerhetsbeskrivare i dokumentationen för kerneldrivrutinen.

Åtkomstkontrollistor

Åtkomstkontrollistor (ACL: er) ger detaljerad kontroll över åtkomsten till objekt. En ACL är en del av säkerhetsbeskrivningen för varje objekt.

Varje ACL innehåller noll eller fler åtkomstkontrollposter (ACE). Varje ACE innehåller i sin tur ett enda SID som identifierar en användare, grupp eller dator och en lista över rättigheter som nekas eller tillåts för detta SID.

ACL:er för enhetsobjekt

ACL för ett enhetsobjekt kan anges på något av tre sätt:

  • Ange standardsäkerhetsbeskrivningen för dess enhetstyp.
  • Skapad programmatiskt av funktionen RtlCreateSecurityDescriptor och som angetts av funktionen RtlSetDaclSecurityDescriptor.
  • Anges i SDDL (Security Descriptor Definition Language) i enhetens INF-fil eller i ett anrop till IoCreateDeviceSecure rutin.

Alla drivrutiner bör använda SDDL i INF-filen för att ange ACL:er för sina enhetsobjekt.

SDDL är ett utökningsbart beskrivningsspråk som gör det möjligt för komponenter att skapa ACL:er i ett strängformat. SDDL används av både användarläge och kernellägeskod. Följande bild visar formatet för SDDL-strängar för enhetsobjekt.

diagram som visar formatet på SDDL-strängar för enhetsobjekt.

Värdet Åtkomst anger vilken typ av åtkomst som tillåts. SID-värdet anger en säkerhetsidentifierare som avgör för vem åtkomstvärdet gäller (till exempel en användare eller grupp).

Följande SDDL-sträng ger till exempel systemåtkomst (SY) till allt och tillåter endast läsåtkomst för alla andra (WD):

“D:P(A;;GA;;;SY)(A;;GR;;;WD)”

Rubrikfilen wdmsec.h innehåller också en uppsättning fördefinierade SDDL-strängar som är lämpliga för enhetsobjekt. Rubrikfilen definierar till exempel SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX enligt följande:

"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GRGWGX;;;RC)"

Det första segmentet i den här strängen ger kerneln och operativsystemet fullständig kontroll över enheten. Det andra segmentet tillåter alla i den inbyggda gruppen Administratörer (BA) att komma åt hela enheten, men inte ändra ACL. Med det tredje segmentet kan alla (WD) läsa eller skriva till enheten, och det fjärde segmentet ger samma rättigheter till ej betrodd kod (RC). Drivrutiner kan använda de fördefinierade strängarna som de är eller som modeller för enhetsobjektspecifika strängar.

Alla enhetsobjekt i en stack ska ha samma ACL:er. Om du ändrar ACL:er på ett enhetsobjekt i stacken ändras ACL:erna i hela enhetsstacken.

Att lägga till ett nytt enhetsobjekt i stacken ändrar dock inte några ACL:er, antingen de för det nya enhetsobjektet (om det har ACL:er) eller de som finns för befintliga enhetsobjekt i stacken. När en drivrutin skapar ett nytt enhetsobjekt och kopplar det överst i stacken ska drivrutinen kopiera ACL:erna för stacken till det nya enhetsobjektet genom att kopiera fältet DeviceObject.Characteristics från nästa lägre drivrutin.

Rutinen IoCreateDeviceSecure stöder en delmängd av SDDL-strängar som använder fördefinierade SID:er som WD och SY. API:er och INF-filer i användarläge stöder den fullständiga SDDL-syntaxen.

Säkerhetskontroller med hjälp av ACL:er

När en process begär åtkomst till ett objekt jämför säkerhetskontroller ACL:erna för objektet med SID:erna i anroparens åtkomsttoken.

Systemet jämför ACE:erna i en strikt uppifrån och ned-ordning och stannar vid den första relevanta matchningen. Därför bör du, när du skapar en ACL, alltid placera nekande ACE:er före motsvarande tillåtande ACE:er. I följande exempel visas hur jämförelsen fortsätter.

Exempel 1: Jämföra en ACL med en åtkomsttoken

Exempel 1 visar hur systemet jämför en ACL med åtkomsttoken för en anroparens process. Anta att anroparen vill öppna en fil som har den ACL som visas i följande tabell.

Exempelfil ACL

Tillåtelse SID Tillträde
Tillåta Redovisning Skriva, ta bort
Tillåta Försäljning Bifoga
Neka Laglig Lägg till, skriva, ta bort
Tillåta Alla Läsa

Den här ACL:en har fyra ACE:er som gäller specifikt för grupperna Redovisning, Försäljning, Juridik och Alla.

Anta sedan att åtkomsttoken för den begärande processen innehåller SID för en användare och tre grupper i följande ordning:

Användaren Jim (S-1-5-21...)

Gruppredovisning (S-1-5-22...)

Juridisk grupp (S-1-5-23...)

Gruppera alla (S-1-1-0)

När du jämför en fil-ACL med en åtkomsttoken letar systemet först efter ett ACE för användaren Jim i filens ACL. Inget visas, så härnäst letar den efter ett ACE för Redovisningsgruppen. Som du ser i föregående tabell visas ett ACE för gruppen Redovisning som den första posten i filens ACL, så Jims process beviljas rätt att skriva eller ta bort filen och jämförelsen stoppas. Om ACE för gruppen Juridisk i stället föregick ACE för gruppen Redovisning i ACL, skulle processen nekas behörighet att skriva, foga till och ta bort i filen.

Exempel 2: Jämföra en ACL med en begränsad token

Systemet jämför en ACL med en begränsad token på samma sätt som det jämför dem i en token som inte är begränsad. Ett nekande-SID i en begränsad token kan dock endast matcha ett Neka ACE i en ACL.

Exempel 2 visar hur systemet jämför en fils ACL med en begränsad token. Anta att filen har samma ACL som visas i föregående tabell. I det här exemplet har dock processen en begränsad token som innehåller följande SID:

Användaren Jim (S-1-5-21...) Neka

Gruppredovisning (S-1-5-22...) Neka

Juridisk grupp (S-1-5-23...) Neka

Gruppera alla (S-1-1-0)

Filens ACL visar inte Jims SID, så systemet fortsätter till redovisningsgruppens SID. Även om filens ACL har ett ACE för redovisningsgruppen som tillåter åtkomst, matchar detta ACE inte SID i processens begränsade token, vilket leder till att åtkomst nekas. Därför fortsätter systemet till den juridiska gruppen SID. ACL:en för filen innehåller ett ACE för gruppen Juridisk som nekar åtkomst, så processen kan inte skriva, lägga till eller ta bort filen.

Privilegier

En behörighet är rätten för en användare att utföra en systemrelaterad åtgärd på den lokala datorn, till exempel att läsa in en drivrutin, ändra tid eller stänga av systemet.

Behörigheter skiljer sig från åtkomsträttigheter eftersom de gäller för systemrelaterade uppgifter och resurser i stället för objekt, och eftersom de tilldelas till en användare eller grupp av en systemadministratör i stället för av operativsystemet.

Åtkomsttoken för varje process innehåller en lista över de behörigheter som beviljats processen. Behörigheter måste vara specifikt aktiverade innan de används. Mer information om behörigheter finns i Privileges i dokumentationen för kerneldrivrutinen.

Filnamnstillägget !acl formaterar och visar innehållet i en åtkomstkontrollista (ACL). Mer information finns i Determining the ACL of an Object and !acl.

Filnamnstillägget !token visar en formaterad vy över ett säkerhetstokenobjekt. Mer information finns i !token.

Tillägget !tokenfields visar namn och förskjutningar av fälten i objektet för åtkomsttoken (TOKEN-strukturen). Mer information finns i !tokenfields.

Tillägget !sid visar säkerhetsidentifieraren (SID) på den angivna adressen. Mer information finns i !sid.

Filnamnstillägget !sd visar säkerhetsbeskrivningen på den angivna adressen. Mer information finns i !sd.

Scenario med Windows-säkerhetsmodell: Skapa en fil

Systemet använder säkerhetskonstruktionerna som beskrivs i Windows-säkerhetsmodellen när en process skapar ett handtag till en fil eller ett objekt.

Följande diagram visar de säkerhetsrelaterade åtgärder som utlöses när en process i användarläge försöker skapa en fil.

flödesschema som illustrerar de säkerhetsrelaterade åtgärderna när en process i användarläge försöker skapa en fil.

Föregående diagram visar hur systemet svarar när ett användarlägesprogram anropar funktionen CreateFile. Följande anteckningar refererar till de inringade talen i bilden:

  1. Ett program i användarläge anropar funktionen CreateFile och skickar ett giltigt Microsoft Win32-filnamn.
  2. Användarläget Kernel32.dll skickar begäran till Ntdll.dll, som konverterar Win32-namnet till ett Microsoft Windows NT-filnamn.
  3. Ntdll.dll anropar funktionen NtCreateFile med Windows-filnamnet. Inom Ntoskrnl.exehanterar I/O Manager NtCreateFile.
  4. I/O Manager packar om begäran till ett Object Manager-anrop.
  5. Objekthanteraren löser symboliska länkar och ser till att användaren har blädderingsrättigheter för sökvägen där filen ska skapas. Mer information finns i Säkerhetskontroller i Object Manager-.
  6. Object Manager anropar systemkomponenten som äger den underliggande objekttyp som är associerad med begäran. För en begäran om att skapa en fil är den här komponenten I/O-hanteraren, som äger enhetsobjekt.
  7. I/O-hanteraren kontrollerar säkerhetsbeskrivningen för enhetsobjektet mot åtkomsttoken för användarens process för att säkerställa att användaren har nödvändig åtkomst till enheten. Mer information finns i Säkerhetskontroller i I/O Manager-.
  8. Om användarprocessen har den åtkomst som krävs skapar I/O-hanteraren ett handtag och skickar en IRP_MJ_CREATE begäran till drivrutinen för enheten eller filsystemet.
  9. Drivrutinen utför ytterligare säkerhetskontroller efter behov. Om begäran till exempel anger ett objekt i enhetens namnområde måste drivrutinen se till att anroparen har de behörigheter som krävs. Mer information finns i Säkerhetskontroller i drivrutinen.

Säkerhetskontroller i Object Manager

Ansvaret för att kontrollera åtkomsträttigheterna tillhör den komponent på högsta nivån som kan utföra sådana kontroller. Om Object Manager kan verifiera anroparens åtkomsträttigheter gör den det. Annars skickar Object Manager begäran till komponenten som ansvarar för den underliggande objekttypen. Komponenten verifierar i sin tur åtkomst, om den kan; om den inte kan skickar den begäran till en ännu lägre komponent, till exempel en drivrutin.

Object Manager kontrollerar ACL:er för enkla objekttyper, till exempel händelser och mutexlås. För objekt som har ett namnområde utför typägaren säkerhetskontroller. I/O-hanteraren anses till exempel vara typägare för enhetsobjekt och filobjekt. Om Objekthanteraren hittar namnet på ett enhetsobjekt eller filobjekt när ett namn parsas, lämnar det namnet till I/O Manager, som i scenariot för att skapa filer som visas ovan. I/O-hanteraren kontrollerar sedan åtkomsträttigheterna om möjligt. Om namnet anger ett objekt i ett enhetsnamnområde inaktiverar I/O-hanteraren i tur och ordning namnet på enhetens (eller filsystemets) drivrutin och den drivrutinen ansvarar för att verifiera den begärda åtkomsten.

Säkerhetskontroller i I/O-hanteraren

När I/O Manager skapar ett handtag kontrollerar det objektets rättigheter mot processåtkomsttoken och lagrar sedan de rättigheter som beviljats användaren tillsammans med handtaget. När senare I/O-begäranden tas emot kontrollerar I/O-chefen de rättigheter som är associerade med handtaget för att säkerställa att processen har rätt att utföra den begärda I/O-åtgärden. Om processen till exempel senare begär en skrivåtgärd kontrollerar I/O-chefen de rättigheter som är associerade med handtaget för att säkerställa att anroparen har skrivåtkomst till objektet.

Om handtaget dupliceras kan rättigheter tas bort från kopian, men inte läggas till i den.

När I/O Manager skapar ett objekt konverteras allmänna Win32-åtkomstlägen till objektspecifika rättigheter. Följande rättigheter gäller till exempel för filer och kataloger:

Win32-åtkomstläge Objektspecifika rättigheter
GENERIC_READ ReadData
GENERIC_WRITE SkrivData
GENERELL_UTFÖR ReadAttributes
ALLMÄNT_ALLT Alla

För att skapa en fil måste en process ha traverseringsrättigheter till de överordnade katalogerna i målsökvägen. Om du till exempel vill skapa \Device\CDROM0\Directory\File.txtmåste en process ha rätt att passera \Device, \Device\CDROM0 och \Device\CDROM0\Directory. I/O-chefen kontrollerar endast blädderingsrättigheterna för dessa kataloger.

I/O-hanteraren kontrollerar blädderingsrättigheterna när filnamnet parsas. Om filnamnet är en symbolisk länk löser I/O-hanteraren den till en fullständig sökväg och kontrollerar sedan blädderingsrättigheterna från roten. Anta till exempel att den symboliska länken \DosDevices\D mappar till Windows NT-enhetsnamnet \Device\CDROM0. Processen måste ha blädderingsrättigheter till katalogen \Device.

Mer information finns i Object Handles and Object Security.

Säkerhetskontroller i drivrutinen

Operativsystemets kernel behandlar varje drivrutin som ett filsystem med sitt eget namnområde. När en anropare försöker skapa ett objekt i enhetens namnområde kontrollerar I/O Manager därför att processen har bläddringsrättigheter till katalogerna i sökvägen.

Med WDM-drivrutiner utför I/O Manager inte säkerhetskontroller mot namnområdet, såvida inte enhetsobjektet har skapats som anger FILE_DEVICE_SECURE_OPEN. När FILE_DEVICE_SECURE_OPEN inte har angetts ansvarar drivrutinen för att säkerställa säkerheten för dess namnområde. Mer information finns i Styra åtkomst till enhetsnamnområde och Skydda enhetsobjekt.

För WDF-drivrutiner är flaggan FILE_DEVICE_SECURE_OPEN alltid inställd, så att det blir en kontroll av enhetens säkerhetsbeskrivning innan ett program får åtkomst till några namn i enhetens namnområde. Mer information finns i Styra enhetsåtkomst i KMDF-drivrutiner.

Windows säkerhetsgränser

Drivrutiner som kommunicerar med varandra och med anropare i användarläge av olika behörighetsnivåer kan anses korsa en förtroendegräns. En förtroendegräns är en exekveringsväg som korsar från en lägre privilegierad process till en process med högre privilegier.

Ju högre skillnad i behörighetsnivåer, desto mer intressant är gränsen för angripare som vill utföra attacker, till exempel en privilegieeskaleringsattack mot den riktade drivrutinen eller processen.

En del av processen med att skapa en hotmodell är att undersöka säkerhetsgränserna och leta efter oväntade sökvägar. Mer information finns i Hotmodellering för drivrutiner.

Alla data som korsar en förtroendegräns är obetrodda och måste verifieras.

Det här diagrammet visar tre kerneldrivrutiner och två appar, en i en appcontainer och en app som körs med administratörsbehörighet. De röda linjerna anger exempel på förtroendegränser.

Diagram som visar drivrutinsattackytan med tre kerneldrivrutiner, en app i en appcontainer och en app med administratörsbehörighet.

Eftersom appcontainern kan ge ytterligare begränsningar och inte körs på administratörsnivå är sökvägen (1) en högre riskväg för en eskaleringsattack eftersom förtroendegränsen är mellan en appcontainer (en process med mycket låg behörighet) och en kerneldrivrutin.

Sökväg (2) är en sökväg med lägre risk eftersom appen körs med administratörsrättigheter och anropar direkt till kerneldrivrutinen. Även om administratören redan har en ganska hög behörighet i systemet, är attackytan från administratör till kärna mindre av ett intressant mål för angripare, men fortfarande en betydande förtroendegräns.

Sökväg (3) är ett exempel på en kodexekveringsväg som passerar flera förtroendegränser och kan förbises om det inte skapas en hotmodell. I det här exemplet finns det en förtroendegräns mellan drivrutin 1 och drivrutin 3, eftersom drivrutin 1 tar indata från användarlägesappen och skickar den direkt till drivrutin 3.

Alla indata som kommer in i drivrutinen från användarläget är inte betrodda och bör verifieras. Indata som kommer från andra drivrutiner kan också vara obetrodda beroende på om den tidigare drivrutinen bara var en enkel genomströmning (t.ex. att data togs emot av drivrutinen 1 från app 1, drivrutinen 1 inte gjorde någon validering av data och bara skickade dem vidare till drivrutin 3). Se till att identifiera alla attackytor och lita på gränser och verifiera alla data som korsar dem genom att skapa en fullständig hotmodell.

Rekommendationer för Windows-säkerhetsmodell

  • Ange starka standard-ACL:er i anrop till IoCreateDeviceSecure rutin.
  • Ange ACL:er i INF-filen för varje enhet. Dessa ACL:er kan lossa snäva standard-ACL:er om det behövs.
  • Ange FILE_DEVICE_SECURE_OPEN egenskap för att tillämpa säkerhetsinställningar för enhetsobjekt på enhetens namnområde.
  • Definiera inte IOCTLs som tillåter FILE_ANY_ACCESS såvida inte sådan åtkomst inte kan utnyttjas på ett skadligt sätt.
  • Använd rutinen IoValidateDeviceIoControlAccess för att öka säkerheten på befintliga IOCTLS som tillåter FILE_ANY_ACCESS.
  • Skapa en hotmodell för att undersöka säkerhetsgränserna och leta efter oväntade sökvägar. Mer information finns i Hotanalys för drivrutiner.
  • Se Checklista för drivrutinssäkerhet för ytterligare rekommendationer för drivrutinssäkerhet.

Se även

skydda enhetsobjekt

Checklista för förarsäkerhet