* 8 *

Objektorientering som sikkerhetsmodell

Ukens faktum

RPC (Remote Procedure Call) dreier seg om eksekvering av funksjoner på fjernmaskiner. RPC begynte med Sun Microsystems' (ONC) infra-struktur for NFS, støttet av Novell og AT&T. Apollo/Hewlett-Packard kom da med et konkurrerende system (NCS) støttet av IBM, DEC(Compaq) og Microsoft. I de senere årene har det kommet statig flere RPC systemer slik som Java RMI, Microsoft's DCOM og CORBA.

Kapitler 17,10 Gollmann
I den siste forelesningen avsluttet vi med en diskusjon om Clark-Wilson modellen og hvordan den forsøker å sikre dataintegritet ved å kreve at brukere benytter spesielle programmer (med begrenset funksjonalitet) for å få tilgang til data. Denne ideen har en viktig parallel i objektorientert programmering. Mange filosofiske påstander har blitt fremmet om objektorientering, men den minst kontroversielle fortåelse av objektorientering er vel som sikkerhetsmodell med tanke på software-integritet. Objektorientering gjør data tilgjengelig på en need to know basis.

Objekter og klasser

Grovt sett kan objektorientering anses som en syntese av to ideer: klassifiseringen av data ved hjelp av abstrakte typer og tilgangskontroll basert på scope (variables rekkevidde/omfang). Selv i ikke-objektorienterte språk har man tilgangskontroll basert på scope. I Algol, Pascal, C, f.eks. kan man definere lokale variabler innenfor et hvilket som helst sett med paranteser:
 /* begin */

  { int localvar;

  }

 /* end */
Når vi sender parametere til funksjoner og subrutiner, kopieres parameterenes verdier til lokale variable, slik at originalene ikke kan røres. Dersom vi kaller, f. eks.
function(i,j);
et sted i et program, hvor funksjonen er definert som

 function (int a, int b)

 { int localvar;

 a = 6;
 b = 7;
 }

vil ikke en forandring av a,b i funksjonen ha noen virkning på de egentlige parametrene i,j, med mindre vi spesielt ber om dette, ved å sende en referanse (peker) til de originale variablene.

Semantiske kverulanter kan diskutere hva objektorientering egentlig betyr. Her er det bra nok å definere alle språk som ikke er lineære og globale (GOTO språk med globale variable) som i hvert fall delvis objektorienterte. Atomære datatyper er primitive objekter. Sammensatte objekter finnes i Pascal (record) og C (struct). Simula, C++ og Java generaliserer datatyper ved å gjøre det mulig å danne klasser som både kan innholde andre dataobjekter og spesialiserte programmer eller metoder for å manipulere dataene. Java går enda lenger enn dette ved å fjerne pekere fra språket og kreve at all tilgang til minne gå via kompilatoren.

Objektorientering består i:

Scope begrenses mer med økende dybde i et hierarki mens privacy/fortroligheten øker.

I likhet med mange andre sikkerhetssystemer krever objektorientering nokså mye av brukeren (programmereren). For noen kan denne prisen være for høy, og det kan føre til at noen programmerere omgår beskyttelsesmekanismene. Det å lage vanntette objektmodeller i ikke-trivielle programmer er svært vanskelig. Tidsinvesteringen kan være enorm da det er nærmest umulig å spesifisere nye (eksperimentelle) programmer nøyaktig ved design stadiet. Sikkerhet passer ikke godt sammen med prototyper for programkonsepter.

Mandatory Access Control eller scope i objektmodeller

Vi observerer minkende scope sikkerhet med økende dybde (økende fortrolighet). Innkapsling og arv fungerer etter de følgende reglene:
  1. Et objekts sikkerhetsnivå skal være større enn det til klasseobjektet. (Høyere betyr sikrere)
  2. En virtuellfunksjons/metodes (subjekts) sikkerhetsnivå skal være større enn det til funksjonen som kaller den, og også større enn det til definisjonsobjektet. (Dette er scope egenskapen)
  3. En virtuellmetode kan kun (execute,read,write) medlemmer av sitt definisjonsobjekt.
  4. En virtuellmetode kan skrive til sitt definisjonsobjekt kun dersom sikkerhetsnivået er lik det til hjemmeobjektet (dvs rekursjon er beskyttet)
  5. En virtuellmetode kan sende en returverdi til metoden som kallte den, kun dersom den har samme sikkerhetsnivå (samme som sist).
  6. Nye objektinstanser skal ha et sikkerhetsnivå som er større enn det til objektet som oppretter dem (objekter lekker ikke).
Globale variable, pekere og referanse-parametere fungerer som covert channels, og kan lage hull i disse reglene.

Klassens rolle i software sikkerhet

Generalisering er sikkerhetens fiende. Spesialisering er sikkerhetens venn.

Klasser i C++ og Java brukes ikke bare til å klassifere data og bygge et privat forum for å manipulere dem, det fins også ganske mye tilleggsteknologi som hjelper mot programmeringsfeil. La oss ta et eksempel fra C++.

    class Box : public Containers

    {
    public:                       // Kan benyttes i en hvilken som helst funksjon

       Box();                     // Unngår minnelekkasjer hvis korrektskrevet
       ~Box();                    

       virtual void Empty();      // Kan overstyres av subklasser. Overstyrer
                                  // foreldreklasse Containers med en mer spesialisert
                                  // (sikrere) funksjon.

       static void Explode();     
       const  void Examine();     // Kan brukes som en covert channel
                                     til å vise private medlemmer til andre objekter

    protected:                    // Kan brukes av medlemmer
                                  // og subklasser
      int   careful1;
      float careful2;

    private:                      // Kun for medlemmer av denne klassen
                                  // eller friends
       int  secret1;
       char secret2;
    }
La oss ta for oss disse en om gangen:

Constructors/destructors og garbage collection

Et problem som oppstår i serverprosesser som kjører over lang tid er at de gradvis bruker mer og mer minne. Til slutt kveler de maskinen som de kjører på (dette har vært et problem med tidlige versjoner av NT). Dette oppstår i programmer som allokerer minne men som ikke frigjør det igjen. Det kalles for en minne lekkasje.

Minne lekkasjer er en sikkerhetssak fordi programmer som spiser opp minne kan brukes til å utføre denial of service angrep. Bruk av constructors/destructors gjør to ting for oss. Det overlater minneallokeringsproblemet til kompilatoren, slik at kompilatoren kan ta seg av å frigjøre minne automatisk. Det betyr også at nye instanser av variable får fornuftige initialverdier--noe som hjelper mot sløve feil, som vi så i ukeoppgavene sist.

Minneallokeringsmodellen i Java er en sentral del av dets forsvar mot sikkerhetsbrudd.

Static og const metoder

Arv og virteulle funksjoner

Klassehierarkiet fungerer som et tilgangskontrollgitter. Multiple inheritance betyr at vi kan få tilgang til en funskjon eller til data ved å gå flere stier gjennom hierarkiet.

  class alpha
     {
     public:
        int A;
        void functionA();
        void printme();
     };

  class beta
     {
     public:
        int B;
        void functionB();
        void printme();
     };

  class alphabet: public alpha, public beta
     {
     public:
        int *letter;
        void words();
     }

Kallet
  alphabet *ptr;

  ptr->printme();
er tvetydig, men ufarlig, da kompilatoren vil klage på det i C++. Hovedproblemet med (multiple) arv er at det øker belastningen til programmereren, det øker ansvaret for å passe på detaljer som kompilatoren ikke kan skjekke. Objekter kan bli tilgjengelig i et program uten at programmereren er klar over det. Dette kan har uheldige konsekvenser. I motsetning til scope, fungerer arv slik at vi beveger oss oppover i et hierarki. Det er mulig at et objekt vil arve informasjon uten at det var intensjonen, dersom hierarkiet blir for dypt.

       ^                        --------
       |                       |        |
       |  U                     --------
       |  p                     /      \
       |  w               --------     --------
       |  a              |        |   |        |
       |  r               --------     --------
       |  d                /   \         /  \

                       more  more      more  more

Multiple inheritance er ulovlig i Java. Der har man interfaces i stedet.

Struct og union

En struct datatype er lik en klasse hvor alle medlemmene er public. Dette er kun en konseptuell innpakning for variabler som er relaterte, slik at programmet blir mer transparent.

En union er noe helt annet. Unions ble innført i C for å unngå fragmentering av minne, noe som vi diskuterte i operativsystemer. Unions har ingenting med sikkerhet å gjøre.

Globale variable og globale funksjoner

Det har blitt populært (faktisk et dogme) å si at bruk av globale variable er "dårlig programmering". La oss vurdere dette.

Argumentasjoner som gjelder globale variable må også gjelde public klassemedlemmer, da public medlemmer er globale innen definisjonsklassen. Hensikten med globale variable er

Her er argumentene for og imot bruk av globale variable. Det at globale variable skal gjøre programmer vanskelige å holde styr på er bare propaganda. Det er lett å holde styr på globale variable ved å innføre en navnekonvensjon f.eks. navn med STOREBOKSTAVER eller suffix variable_glb etc.

CORBA

En av hensiktene med prosedyre-baserte programmeringsspråk er at strukturen i slike programmer gjør det lettere å gjenbruke kode ved å danne biblioteker. Unix innførte shared libraries for å gjøre tilgang til biblioteker mer effektiv. I steden for å appendere et helt bibliotek til hvert program, deler alle programmer et bibliotek som er laget av fleskibel, omadresserbar kode. For å kunne bruke et slikt bibliotek må et program bruke en funskjonsmegler eller dynamic link loader (ld.so) som laster inn funksjonene som trengs av en prosess. Windows fulgte denne ideen senere ved å innføre DLLer (dynamically loadable library).

Det er naturlig å utvide denne tankegangen til hele nettverket, slik at vi har distributed shared libraries. I et objektorientert språk går vi et skritt lenger og definerer klasseobjekter og objektmetoder slik som standardbibliotekene i C++ eller Java, hvor disse kan lastes ned av en hvilken som helst maskin. Problemet da er at ulike operativsystemer og implementasjoner er ukompatible.

CORBA (The Common Object Request Broker Architecture) er en løsning på dette problemet. Det gir oss en infrastruktur som er standardisert og skjuler forskjellene mellom operativsystemer og programmeringsspråk. Det er en generell bibliotektjeneste for objekter. En objektforespørselsmegler eller Object Request Broker (ORB) kan betraktes som en `software bus' mellom klienter (brukerprogrammer) og servere. ORBen håndterer forespørsler fra klienter og passer på at de eksekveres på en server. Objekter og metoder eksekveres og lagres på en fjernmaskin (CORBA er et RPC-system). Brukerprogrammet blir da en stub (avstumpet skjelett).

CORBA påstår å ha en sikker arkitektur som passer godt i flerbrukermiljøer. CORBA sikkerhet inkluderer

Siden CORBA er en tjeneste kan den begrense hvilke operasjoner som utføres av en klient slik at sikkerhet kan bevares. Men dette er betinget av serverens egen sikkerhet.

Ukens tanke

Kompilerte språk utfører mange kontroller og varsler programmerere om potensielt farlig kode. Gjør dette kompilerte språk sikrere enn scriptspråk slik som Perl eller Visual Basic?

Back