Secure Application Roles Beheer de toegang tot de database 1. Inleiding Het realiseren van geautoriseerde toegang tot een database lijkt eenvoudig. Echter, vaak blijkt dat dezelfde combinatie van gebruikersnaam en wachtwoord zowel toegang geeft tot de applicatie als tot de database. Hierdoor kunnen gebruikers buiten de applicatie om met bijvoorbeeld Toad of SQL*Plus de database benaderen. In de praktijk ziet men vaak dat rechten in de database dermate ruim zijn dat hierdoor de gebruiker in potentie veel kwaad kan. In dit artikel wordt besproken hoe voorkomen kan worden dat een gebruiker rechtstreeks inlogt op de database. Hierbij wordt gebruik gemaakt van Secure Application Roles. 2. Ontwerp Het ontwerp van de toegangsbeveiliging bepaalt de mogelijkheden van misbruik. De ene oplossing biedt voordelen ten opzichte van een andere, maar het gebruik van Role Based Access Control, kortweg RBAC, is een veel voorkomende keuze. Over RBAC is veel informatie te vinden, bijvoorbeeld op http://csrc.nist.gov/groups/SNS/rbac/ en een veel voorkomend praktijkvoorbeeld staat beschreven in de volgende alinea. Een applicatie bestaat uit verschillende functionaliteiten. Functionaliteit kan daarbij gegroepeerd worden, zodat bepaalde functies eenvoudig aan een rol gekoppeld kunnen worden. Voor het wijzigen van de klantgegevens kan bijvoorbeeld de rol rol_wijzigen_klant aanwezig zijn. Deze rol beschikt over de privileges om de onderliggende database objecten te wijzigen via dml-statements. Dit principe staat in onderstaande figuur afgebeeld, waarbij er een n-op-n relatie bestaat tussen de verschillende objecten. user role privilege gebruiker Alhoewel er verschillende ontwerpen mogelijk zijn wordt in de rest van dit artikel RBAC als uitgangspunt gehanteerd. De centrale vraag bij het toepassen van RBAC binnen de Oracle database is hoe en wanneer we de relatie leggen tussen users en rollen. 3. Oplossingen Om de toegang tot applicaties en databases te beheren zijn er verschillende alternatieven. Een mogelijkheid is initieel inloggen onder een guest account en vervolgens “onder water” inloggen met het gebruikers account. Hierbij kan bijvoorbeeld gebruik gemaakt worden van account informatie van het operating system. Is de mogelijkheid aanwezig om een zelf gedefinieerd operating system account te gebruiken, dan is deze toegangsbeveiliging echter onvoldoende. Ingo Wevers 1 Ook kunnen we rollen hanteren waarbij deze rollen alleen via een wachtwoord te activeren zijn. Dit vereist echter weer noodzakelijke aanpassingen indien de wachtwoorden worden gewijzigd. Het gebruik van logon triggers biedt mogelijkheden om gebruikers toegang te ontzeggen, maar niet om rollen te activeren. Dit wordt veroorzaakt door het feit dat logon triggers als definer rights gedefinieerd zijn. Een logon trigger wordt namelijk uitgevoerd als de user sys en een aanroep naar een package waarbinnen rollen gezet worden, zal deze rol vervolgens activeren voor de sys user. Het gebruik van Secure Application Roles biedt de mogelijkheid om rollen uitsluitend te activeren door het uitvoeren van een package. Dit is een effectief mechanisme, omdat de applicatie op het moment van inloggen de rol kan activeren. Het vereist naast de initiële inrichting geen extra inspanningen op het gebied van user management en is eenvoudig aan te passen bij functie-wijzigingen. In de volgende paragraaf wordt Secure Application Roles nader uitgewerkt. 4. Activeren van rollen via Secure Application Roles In onderstaande figuur staat het principe Secure Application Roles afgebeeld, waarna een korte toelichting volgt. User Application Database Identification Authentication Package SetRole for user guard package Authorisation Authorisation table De user brengt een sessie tot stand met de applicatie. De applicatie bevat de modulen identificatie, authenticatie en autorisatie. Door middel van de combinatie gebruikersnaam en wachtwoord handelt de applicatie de identificatie en authenticatie af. Vervolgens gaat de autorisatie module, het guard package in bovenstaande figuur, verschillende controles uitvoeren. De keuze van het soort controle kan bijvoorbeeld gekoppeld worden aan de webserver naam waar de sessie vandaan komt en het al dan niet voorkomen van de gebruiker die in de tabel met autorisatie gegevens. Juist dit autorisatie package dat naar eigen inzicht ontworpen kan worden biedt veel mogelijkheden, waarbij er gebruik gemaakt kan worden van de context van die gebruiker. Indien het guard package de controles uitgevoerd heeft, wordt de package procedure SetRole aangeroepen. De uitvoering van SetRole zorgt ervoor dat de juiste rol geactiveerd wordt voor de gebruiker. Het package is in staat de rol te activeren, omdat in het “CREATE ROLE” statement “IDENTIFIED USING <package>” is gebruikt. Wrapping en auditing van het package kunnen vervolgens een bijdrage leveren aan de onzichtbaarheid van de controles en de vaststelling dat het autorisatie package inderdaad op basis van een enkele applicatie module wordt aangeroepen. Ingo Wevers 2 Onderstaand een voorbeeld van de SQL en PL/SQL code voor het implementeren van Secure Application Roles. 1. Maken omgeving -- Tablespace users dient aanwezig te zijn CREATE USER test_user IDENTIFIED BY test DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp; GRANT CREATE SESSION TO test_user; CREATE USER monitor IDENTIFIED BY test DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp; GRANT DBA TO MONITOR; CREATE USER test_owner IDENTIFIED BY test DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp; GRANT CREATE SESSION TO test_owner; GRANT CREATE TABLE TO test_owner; ALTER USER test_owner QUOTA UNLIMITED ON users; CONNECT test_owner/test CREATE TABLE customer (naam VARCHAR2(8)); INSERT INTO customer VALUES ('WEVERS'); COMMIT; 2. Secure Application Roles implementeren -- Maken van een rol die geactiveerd kan worden door een package. CONNECT MONITOR/test CREATE ROLE write IDENTIFIED USING monitor.write_guard; GRANT SELECT,INSERT,DELETE,UPDATE ON test_owner.customer TO write; -- Toekennen van privileges aan de rol CREATE ROLE read IDENTIFIED USING monitor.read_guard; GRANT SELECT ON test_owner.customer TO read; -- Maken van een autorisatie-tabel DROP TABLE MONITOR.USERS; CREATE TABLE MONITOR.USERS (OSUSER VARCHAR2(6), ROL VARCHAR2(3)) TABLESPACE users; commit; grant select on users to test_user; -- Package maken dat de rol kan activeren voor een gebruiker CREATE OR REPLACE PACKAGE monitor.write_guard AUTHID CURRENT_USER AS PROCEDURE set_role; END; / CREATE OR REPLACE PACKAGE BODY monitor.write_guard AS PROCEDURE set_role AS BEGIN DBMS_SESSION.set_role ('write'); EXCEPTION WHEN OTHERS THEN -- audit info, temporary null NULL; END; END; / CREATE OR REPLACE PACKAGE monitor.read_guard AUTHID CURRENT_USER AS PROCEDURE set_role; Ingo Wevers 3 END; / CREATE OR REPLACE PACKAGE BODY monitor.read_guard AS PROCEDURE set_role AS BEGIN DBMS_SESSION.set_role ('read'); EXCEPTION WHEN OTHERS THEN -- audit info, temporary null NULL; END; END; / -- Package maken dat de controles uitvoert en afhankelijk van de functie het juiste package aanroept en daarmee de rol activeert. CREATE OR REPLACE PACKAGE monitor.access_guard AUTHID CURRENT_USER AS PROCEDURE set_role; END; / --In eigen test <SERVERNAAM APPLICATIE> vervangen door localhost.localdomain CREATE OR REPLACE PACKAGE BODY monitor.access_guard AS FUNCTION isapplicationhost RETURN BOOLEAN AS BEGIN RETURN (SYS_CONTEXT('USERENV','HOST') = '<SERVERNAAM APPLICATIE>'); END; PROCEDURE set_role AS v_aantal integer := 0; BEGIN select count(*) into v_aantal from monitor.users b where b.osuser = SYS_CONTEXT('USERENV','OS_USER') and b.rol = 'DBA'; IF (v_aantal > 0) and (isapplicationhost) THEN monitor.write_guard.set_role; ELSE monitor.read_guard.set_role; END IF; EXCEPTION WHEN OTHERS THEN -- audit info, temporary null NULL; END; END; / GRANT EXECUTE ON monitor.access_guard TO test_user; 3. Test connect monitor/test -- Zorg voor registratie in de autorisatie table insert into MONITOR.USERS values ('oracle','DBA'); commit; --Stel vast dat je de rol “write” hebt ontvangen, ervan uitgaande dat je inlogt met het OSaccount oracle connect test_user/test; Ingo Wevers 4 select * from session_roles; --Voer vanuit de applicatie voor de user die wil inloggen het package uit exec monitor.access_guard.set_role; --Check de rollen en stel vast dat je een record kunt verwijderen select * from session_roles; select * from test_owner.customer; delete from test_owner.customer; rollback; --Voor de tweede test het record verwijderen, zodat de “read” rol wordt toegekend connect monitor/test delete from MONITOR.USERS where osuser = 'oracle'; commit; --Connect als de test_user connect test_user/test; select * from session_roles; --Voer het package wederom uit exec monitor.access_guard.set_role; --Stel vast dat je de rol “read” hebt ontvangen select * from session_roles; select * from test_owner.customer; --Een delete mag niet slagen delete from test_owner.customer; --Opruimen connect / as sysdba drop user test_user; drop user test_owner cascade; drop user monitor cascade; drop role read; drop role write; 5. Conclusie Secure Application Roles biedt een oplossing voor beheersbare toegang tot de database. Het is een oplossing die erg geschikt is in situaties waarbij gebruik gemaakt wordt van Role Based Access Control. Het toekennen van rollen wordt niet statisch geregeld, maar dynamisch vanuit de applicatie op het moment dat iemand inlogt. Hierbij is een duidelijke autorisatie-structuur van de applicatie noodzakelijk. Het is een flexibele oplossing die beheersbaar en onderhoudbaar is. Een verandering van functie betekent slechts een wijziging in de autorisatie gegevens. Eisen voor het succesvol toepassen van Secure Application Roles zijn een goed doordacht RBAC ontwerp, een duidelijk mechanisme voor autorisatie, integratie van een autorisatie module in de applicatie en samenwerking tussen ontwikkelaars en dba's. Over de auteur: Ingo Wevers BSc is werkzaam als Oracle consultant binnen GRID-IT en richt zich met name op Oracle security en Oracle Streams. Reacties op dit artikel graag per mail naar [email protected] Ingo Wevers 5