Exceptionfault
Erfahrenes Mitglied
Ein wichtiges Thema in der Datenbank ist und bleibt die Sicherheit der Daten. Wie stelle ich sicher, dass jeder auch nur das sehen kann was er sehen darf?
Die häufigste Methode ist die Umsetzung einer Sicherheitslogik in der Applikation. Nehmen wir als Beispiel dieses Forum: Über das Login ist der Webapplikation der Benutzer bekannt. Anhand der eindeutigen BenutzerID werden mir in meinem Postfach auch nur meine Nachrichten angezeigt. Was aber, wenn es mir gelingen würde um die Logik der Webapplikation an die Datenbank zu gelangen? Klar, mir stünde die komplette Datenbank offen.
Die Frage ist doch also, wie kann ich die Sicherheit in der Datenbank umsetzen, dass wenn ein Benutzer schon über Umwege in die Datenbank kommt, dass er trotzdem nur zu dem kommt, zu dem er wirklich Zugang haben sollte. Ganz davon abgesehen würde es die Applikationen doch wesentlich vereinfachen wenn man von der Datenbank sowieso nur die Daten bekommt die man grade anzeigen darf...
Ich möchte hier mal eine (wie ich finde) recht gelungene Lösung zeigen, die aber wiedermal nur Oracle Benutzern zu Gute kommt. Die Rede ist vom kostenfreien Feature ROW LEVEL SECURITY. Einzige Voraussetzung ist der Einsatz einer Enterprise Edition und einer Oracle Version >= 9.2.0.
Zunächst unsere Testumgebung:
Wir haben also 2 Tabellen und drei Benutzer. Die Datenbank erlaubt keinem der User Zugriff auf die Tabelle APP_USERS, dafür aber vollen Zugriff auf APP_DATA. Wenn sich Bill nun also anmeldet sieht er folgendes:
Nicht so gut...
Wir brauchen also eine Funktion, die unsere daten für den passenden User einschränkt. Und diese Funktion sieht ganz einfach aus:
Wir selektieren das Land des gerade angemeldeten Benutzers aus der APP_USERS Tabelle und geben einen String zurück der einer "WHERE" Klausel recht nahe kommt.
Nun müssen wir die Funktion noch an die Tabelle binden:
Und hier das Ergebnis:
Und die Überraschung:
Die Policy gilt also auch für den Besitzer der Tabelle und sogar für den User System. Lediglich SYS sieht alles. Dadurch dass auch System eingeschränkte Rechte hat, würde er bei einem Export der Daten mit dem Tool "exp" auch keine Daten bekommen, also Sicherheit auf der tiefsten Ebene.
Ich hoffe ich habe ein interessantes Thema angeschnitten, bei Fragen helfe ich natürlich gerne weiter.
Die häufigste Methode ist die Umsetzung einer Sicherheitslogik in der Applikation. Nehmen wir als Beispiel dieses Forum: Über das Login ist der Webapplikation der Benutzer bekannt. Anhand der eindeutigen BenutzerID werden mir in meinem Postfach auch nur meine Nachrichten angezeigt. Was aber, wenn es mir gelingen würde um die Logik der Webapplikation an die Datenbank zu gelangen? Klar, mir stünde die komplette Datenbank offen.
Die Frage ist doch also, wie kann ich die Sicherheit in der Datenbank umsetzen, dass wenn ein Benutzer schon über Umwege in die Datenbank kommt, dass er trotzdem nur zu dem kommt, zu dem er wirklich Zugang haben sollte. Ganz davon abgesehen würde es die Applikationen doch wesentlich vereinfachen wenn man von der Datenbank sowieso nur die Daten bekommt die man grade anzeigen darf...
Ich möchte hier mal eine (wie ich finde) recht gelungene Lösung zeigen, die aber wiedermal nur Oracle Benutzern zu Gute kommt. Die Rede ist vom kostenfreien Feature ROW LEVEL SECURITY. Einzige Voraussetzung ist der Einsatz einer Enterprise Edition und einer Oracle Version >= 9.2.0.
Zunächst unsere Testumgebung:
Code:
CREATE TABLE APP_USERS
(
USERNAME VARCHAR2( 35 ) NOT NULL,
COUNTRY VARCHAR2( 2 ) NOT NULL
);
INSERT INTO APP_USERS VALUES ( 'MIKE', 'DE' );
INSERT INTO APP_USERS VALUES ( 'JOE', 'US' );
CREATE TABLE APP_DATA
(
UN_ID NUMBER( 5,0 ) NOT NULL,
COUNTRY VARCHAR2( 2 ) NOT NULL,
DATAFLD VARCHAR2( 50 ) NOT NULL
);
INSERT INTO APP_DATA VALUES ( 1, 'DE', 'Das sind geheime Daten!' );
INSERT INTO APP_DATA VALUES ( 2, 'DE', 'Nur Mike darf sie sehen!' );
INSERT INTO APP_DATA VALUES ( 3, 'US', 'Joe hat auch geheime Daten!' );
INSERT INTO APP_DATA VALUES ( 4, 'IT', 'Geheimes Pizzarezept... ;-)' );
COMMIT;
CREATE USER MIKE IDENTIFIED BY mike DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP;
CREATE USER JOE IDENTIFIED BY joe DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP;
CREATE USER BILL IDENTIFIED BY bill DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP;
GRANT CREATE SESSION TO MIKE;
GRANT CREATE SESSION TO JOE;
GRANT CREATE SESSION TO BILL;
GRANT SELECT, INSERT, UPDATE, DELETE ON APP_DATA TO MIKE, JOE, BILL;
Wir haben also 2 Tabellen und drei Benutzer. Die Datenbank erlaubt keinem der User Zugriff auf die Tabelle APP_USERS, dafür aber vollen Zugriff auf APP_DATA. Wenn sich Bill nun also anmeldet sieht er folgendes:
Code:
SQL> conn bill/bill
Connected.
SQL> select * from rls.app_data;
UN_ID CO DATAFLD
---------- -- --------------------------------------------------
1 DE Das sind geheime Daten!
2 DE Nur Mike darf sie sehen!
3 US Joe hat auch geheime Daten!
4 IT Geheimes Pizzarezept... ;-)
Nicht so gut...
Wir brauchen also eine Funktion, die unsere daten für den passenden User einschränkt. Und diese Funktion sieht ganz einfach aus:
Code:
CREATE OR REPLACE FUNCTION app_data_sec (object_schema IN VARCHAR2, object_name VARCHAR2)
RETURN VARCHAR2
IS
v_country APP_USERS.COUNTRY%TYPE;
BEGIN
SELECT COUNTRY
INTO v_country
FROM APP_USERS
WHERE USERNAME = USER;
RETURN 'COUNTRY = ''' || v_country || '''';
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN '1=2';
END;
/
Nun müssen wir die Funktion noch an die Tabelle binden:
Code:
BEGIN
dbms_rls.add_policy(
object_schema => 'RLS',
object_name => 'APP_DATA',
policy_name => 'APP_DATA_POLICY',
function_schema =>'RLS',
policy_function => 'APP_DATA_SEC'
);
END;
/
Code:
SQL> conn mike/mike
Connected.
SQL> select * from rls.app_data;
UN_ID CO DATAFLD
---------- -- --------------------------------------------------
1 DE Das sind geheime Daten!
2 DE Nur Mike darf sie sehen!
SQL> conn joe/joe
Connected.
SQL> select * from rls.app_data;
UN_ID CO DATAFLD
---------- -- --------------------------------------------------
3 US Joe hat auch geheime Daten!
SQL> conn bill/bill
Connected.
SQL> select * from rls.app_data;
no rows selected
Code:
SQL> conn rls/rls
Connected.
SQL> select * from app_data;
no rows selected
SQL> conn system/oracle
Connected.
SQL> select * from rls.app_data;
no rows selected
SQL> conn / as sysdba
Connected.
SQL> select * from rls.app_data;
UN_ID CO DATAFLD
---------- -- --------------------------------------------------
1 DE Das sind geheime Daten!
2 DE Nur Mike darf sie sehen!
3 US Joe hat auch geheime Daten!
4 IT Geheimes Pizzarezept... ;-)
Ich hoffe ich habe ein interessantes Thema angeschnitten, bei Fragen helfe ich natürlich gerne weiter.