Indhold:
-Overordnede-
-Sideordnede-
|
Intel arkitekturen - Hvad er 'protected mode'?![]() Om root-kits, kernel- og usermode.Der jævnligt alarmerende meldinger om "root kits" og deres hærgen i det skjulte. Er det nu endnu et af disse buzzwords, der ikke rigtig betyder noget - eller hva'? Hvad er et 'root kit' så?Betegnelsen dækker over over teknikker og/eller programmer til at skaffe adgang til de dele af et computersystem, som kun super brugere eller system administratorer normalt har adgang til. Udtrykket 'root' hentyder til brugernavnet for administratoren på mange Unix og Linux systemer. Det er den bruger, der så vidt jeg ved som regel hedder 'Administrator' i Windows. I Unix/Linux verdenen arbejdes der traditionelt med en sikkerhedsmodel, hvor denne 'root' bruger har uindskrænket adgang til hele systemet bl.a. til alle filer og filsystemer. At have en 'root' bruger på denne måde er et princip, hvis svagheder har medført at man på det seneste har introduceret den såkaldte ACL teknik (ACL = "Access Control Lists"). På denne måde kan rettigheder til system objekter tildeles mere gradueret end med den traditionelle 'alt eller alm. bruger' metode. Men hvis et program kan skaffe en (mis-)bruger, der ikke burde have det, samme rettigheder som 'root', så er vejen banet for lidt af hvert. Det vil f.eks. sige, at væsentlige systemfiler - som alm. brugere ikke har skrive rettigheder til - kan ændres. Dette udnyttes typisk til at modificere visse centrale programmer i systemet på en sådan måde, at det eller de ondsindede programmer ikke dukker op i lister over kørende processer, og at den eller de filer, sådanne programmer producerer som et led i deres ugerninger, ikke dukker op i fil listninger o.l. De trin, der kan fører til denne tilstand, vil typisk være:
Som system administrator skal man så vidt muligt sørge for, at step 1 ikke lykkes for indtrængeren. Er man først i fase 2, er det svært både at finde og fjerne 'root kittet'. Det kræver en ganske stor teknisk viden for at klare det. Det kræver også forudseenhed, idet man typisk skal starte fra en 'clean' CD (hvor ingen filer kan skrives i), og så lokalisere, hvad der er pillet ved i det syge system. Men det er ingenlunde trivielt. En geninstallation kan meget vel komme på tale. Vedrørende step 1, så er spørgsmålet, hvad "På en eller anden måde" dækker over. Her tror jeg, at især følgende grundregler er en nødvendige:
System sikkerhed.Som bekendt er Linux et flerbruger system. Som følge heraf skal det kunne afvikle flere programmer 'samtidigt'. Når jeg sætter gnyffer omkring ordet samtidigt, så betyder det, at på systemer med kun én CPU, så er det kun tilsyneladende samtidigt. Her laver CPU'en lidt på process A, så lidt på process B, C og D o.s.v. indtil det bliver A's tur igen. Desuden skal styresystemet tildele ressourcer (hukommelse, hard disk adgang, IO porte, skærm + tastatur m.v.) på en retfærdig måde til de forskellige processer. Det skal foregå på en sådan måde, at de enkelte programmer eksempelvis ikke kan skrive i hinandens hukommelse. Heraf følger, at der altså skal eksistere en mekanisme, der tillader at markere, hvilket program, der 'ejer' en resurse - f.eks. en memory blok. Indirekte adresseringDet foregår i Intel (IA-32 og kompatible) CPU'er ved at de registre, der f.eks. udpeger memory blokke, gør dette indirekte via en såkaldt 'descriptor' tabel, hvoraf der normal findes to typer GDT = "Global Descriptor Table" eller LDT = "Local Descriptor Table". Disse tabeller er arrays opbygget i hukommelsen. De består af et antal 'descriptorer', som f.eks. kan svare til en memory blok. Jeg skal ikke her gå i detaljer, men blot nævne, at det er descriptoren til en memory blok, der angiver bl.a. liniær adresse, størrelse og adgangsrettigheder til det pågældende system objekt - her altså en klump hukommelse. ![]() Den venstre halvdel af figuren "Segmentation" skitserer princippet, hvor segment-delen af en logisk adresse via en 'Segment Descriptor' bruges til at pege på en memory blok i et lineært adresserum. Offset delen af adressen lægges så til for at få den lineære adresse. Hvis der ikke bruges 'paging', så stopper det her. Den højre del illustrerer 'paging' - altså den mekanisme, hvorved det samlede lager (hvoraf en del kan befinde sig i en swap-fil på f.eks. harddisk) er opdelt i sider (pages). Den lineære adresse opdeles i 3 dele, som refererer til et 'Page Directory', der så peger på en 'Page Table', hvis poster mapper til et fysisk side i adresserummet. Den endelige adresse får man så ved at lægge en offset del til. Idéen er så, at hvis en given memory 'page' ikke er til rådighed i maskinens arbejdslager (RAM), så genereres en 'exception', d.v.s. en slags interrupt, der medfører, at styresystemet kan tage over og indlæse den (de) manglende pages i RAM lageret. Er der ikke plads her, må en eller flere 'gamle' pages skrives ud i swap-filen. Men der er mere. Hvordan forhindres det, at hvilket program som helst kan ændre disse DT'ere - og andre system objekter med for den sags skyld? Privilege LevelsDet gøres ved, at man arbejder med flere 'Privilege Levels' (PL). På IA-32 kompatible CPU'er (Intel i386 familien) findes 4. De er nummereret fra 0 (mest priviligeret) til 3 (mindst priviligeret). I al almindelighed angives CPL (Current Privilege Level) i CS (Code Segment) registret, og det vil svare til det i code segment descriptoren angive PL. Afhængigt af CPL er der visse instruktioner, som enten ikke kan udføres - eller som virker forskelligt. Det nytter jo ikke, at et bruger program (som normalt kører med CPL = 3) selv kan opgradere sig til f.eks. CPL = 0, som normalt kun bruges af styresystemets ædlere dele. Instruktioner, der manipulere sådanne kritiske elementer, kan kun udføres af kode, der kører med CPL = 0. De forskellige privilege levels kaldes også for "ringe". Kode siges således at køre i f.eks. ring 0 (bruges af styresystemet) eller i ring 3 med færre rettigheder (til brugerprogrammer). ![]() Når et brugerprogram med fra ring 3 skal benytte en systemrutine i ring 0 til at udføre en eller anden service for sig, hva' gør man så? Til dette formål findes såkaldte "call gates". En sådan call gate har også en descriptor og benyttes, når et kald fra ring 3 (bruger programmer) til ring 0 (systemkald) skal foretages. I Linux benyttes kun ring 0 og 3. Jeg ved ikke, hvordan billedet er i Windows. Generelt gælder, at kald kun er muligt til kode, der kører i en ring med et højere PL (numerisk lavere) end koden, hvorfra der kaldes. Ellers ville en systemrutine - der formodes at være fejlfri (i en ideel verden!) - måske kunne bringes til at kalde tilbage til ring 3 (og dermed til potentielt usikker kode). Og det går jo ikke! Som almindelig - men sikkerheds bevidst - bruger behøver man naturligvis ikke at vide alt det her. Man kan blot tage det som en illustration af, at det ikke er ganske trivielt at skrive sikker kode som udnytter disse muligheder optimalt - især ikke, hvis der er tale om kode, der er en del af et styresystem og dermed skal afvikles med ring 0 rettigheder. Det er derfor ganske umuligt fuldstændig at undgå fejl. Det er derfor det er vigtigt at holde sit system opdateret med de rettelser som seriøse udbydere stiller til rådighed. Denne lille intro fortæller langt fra alt; men kan forhåbentlig give en fornemmelse af visse af principperne for CPU'ens virkemåde. Skulle man ikke desto mindre være interesseret, så kan Intels telefonbogs tykke håndbøger downloades som PDF filer f.eks. her. Mars 2010 |