Neue PL/SQL Features V - Inherit Privileges
Im heutigen Blogeintrag in der Reihe der neuen PL/SQL Features soll es um ein Security-Feature ab der Version 12c gehen. Ab dieser Version wurde das Berechtigungskonzept für dynamisches Statements in PL/SQL geändert. Für einen PL/SQL-Block kann festgelegt werden, mit wessen Berechtigungen er ausgeführt wird, entweder mit denen des Erstellers (Definer Rigths) oder mit denen des Aufrufenden (Invoker Rights). Der Standard ist dabei immer Definer Rights. Mit dem Standard ergeben sich keine Änderungen, da der Ersteller selbst alle nötigen Rechte zum Erstellen und Ausführen der Prozedur besitzen muss. Bei Invoker Rights hingegen ist es anders, der Aufrufende kann z.B. mehr Privilegien haben als der Ersteller. Der Ersteller könnte dies in dynamischen SQL ausnutzen, die dafür nötigen Berechtigungen werden erst zur Laufziet geprüft, zum Zeitpunkt der Erstellung ist eine solche Prüfung schlichtweg noch gar nicht möglich.
Stellen wir uns folgendes Szenario vor. Es gibt einen Applikations-DBA mit weitrechenden Berechtigungen. Dieser gibt einen Programmierauftrag an einen Entwickler mit weniger Berechtigungen. Der Entwickler wird das umsetzen, versucht aber gleichzeitig, die Berechtigungen des Applikations-DBAs auszunutzen. Wie funktioniert das? Zuerst legen wir beispielhaft beide Benutzer an und vergeben die entsprechenden Berechtigungen.
SQL> create user appdba identified by "SecreT-01#" default tablespace users;
User created.
SQL> grant dba to appdba;
Grant succeeded.
SQL> create user appdev identified by "SecreT-01#" default tablespace users;
User created.
SQL> grant create session, create procedure to appdev;
Grant succeeded.
Nun beginnt der Entwickler mit seinem Programmierauftrag, verbindet sich zunächst mit der Datenbank und prüft die an ihn vergebenen Rollen.
SQL> conn appdev/SecreT-01#@testdb
Connected.
SQL> select * from session_roles;
no rows selected
Als nächstes erstellt er eine PL/SQL Prozedur, die mit Invoker Rights, also mit den Rechten des Aufrufenden, ausgeführt wird. Darin versucht er sich mittels dynamischen SQLs DBA-Rechte zu geben. Da die Rechteprüfung für dieses dynamische SQL erst zur Laufzeit durchgeführt werden kann, kann er die Prozedur auch ohne Fehler erstellen.
SQL> create or replace procedure prc_programmierauftrag
2 AUTHID CURRENT_USER
3 as
4 begin
5 execute immediate 'grant dba to appdev';
6 end;
7 /
Procedure created.
SQL> grant execute on prc_programmierauftrag to appdba;
Grant succeeded.
Ausführen kann er selbst diese Prozedur dann natürlich nicht.
SQL> exec prc_programmierauftrag;
BEGIN prc_programmierauftrag; END;
*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "APPDEV.PRC_PROGRAMMIERAUFTRAG", line 5
ORA-06512: at line 1
Da er aber dem Applikations-DBA nun Rechte zum Ausführen der Prozedur gegeben hat, meldet er die Fertigstellung der Prozedur mit der Bitte um einen Test. Der Applikations-DBA führt die Prozedur daher aus und erhält auch keine Fehlermeldung.
SQL> conn appdba/SecreT-01#@testdb
Connected.
SQL> exec appdev.prc_programmierauftrag;
PL/SQL procedure successfully completed.
Der Entwickler hingegen ist hoch erfreut und prüft, ob seine Prozedur auch tatsächlich das gewünschte Ergebnis erzielt hat.
SQL> conn appdev/SecreT-01#@testdb
Connected.
SQL> select * from session_roles;
ROLE
--------------------------------------------------------------------------------
DBA
SELECT_CATALOG_ROLE
EXECUTE_CATALOG_ROLE
CAPTURE_ADMIN
EXP_FULL_DATABASE
IMP_FULL_DATABASE
DATAPUMP_EXP_FULL_DATABASE
DATAPUMP_IMP_FULL_DATABASE
GATHER_SYSTEM_STATISTICS
OPTIMIZER_PROCESSING_RATE
EM_EXPRESS_BASIC
EM_EXPRESS_ALL
SCHEDULER_ADMIN
HS_ADMIN_SELECT_ROLE
HS_ADMIN_EXECUTE_ROLE
XDBADMIN
XDB_SET_INVOKER
WM_ADMIN_ROLE
JAVA_ADMIN
OLAP_XS_ADMIN
OLAP_DBA
21 rows selected.
Wie man sieht, hat der Entwickler nun plötzlich 21 gegrantete Rollen durch das dynamische SQL erhalten und könnte nun unbemerkt viele unerlaubte Dinge in der Datenbank tun.
Die Fragen, die sich daraus ergeben, woher kommt das und wie kann man das verhindern? Die Frage nach der Ursache ist einfach, das Verhalten war bis einschließlich Oracle Version 11.2 der Standard. Mit 12.1 wurde das Recht INHERIT PRIVILEGES eingeführt, mit dem man diesen Effekt verhindern kann. Um aber zur Vorversion kompatibel zu bleiben, vergibt die Datenbank dieses Recht automatisch für jeden neu angelegten Benutzer an PUBLIC. Das kann man folgendermassen prüfen:
SQL> SELECT grantor, grantee, privilege
2 FROM dba_tab_privs
3 WHERE grantee = 'PUBLIC'
4 AND privilege = 'INHERIT PRIVILEGES'
5 AND grantor like 'APPD%';
GRANTOR GRANTEE PRIVILEGE
-------------------- -------------------- ----------------------------------------
APPDBA PUBLIC INHERIT PRIVILEGES
APPDEV PUBLIC INHERIT PRIVILEGES
Wir haben dieses Recht nicht explizit vergeben und doch ist es offenbar vorhanden. Die Lösung ist also, das INHERIT PRIVILEGES Recht gar nicht zu vergeben bzw. wieder zu entziehen. Die Prozedur kann dann nicht mehr fehlerfrei ausgeführt werden, wenn der Ersteller der Prozedur nicht explizit die benötigten Rechte erhalten hat.
SQL> revoke inherit privileges on user appdba from public;
Revoke succeeded.
SQL> conn appdba/SecreT-01#@testdb
Connected.
SQL> exec appdev.prc_programmierauftrag;
BEGIN appdev.prc_programmierauftrag; END;
*
ERROR at line 1:
ORA-06598: insufficient INHERIT PRIVILEGES privilege
ORA-06512: at "APPDEV.PRC_PROGRAMMIERAUFTRAG", line 1
ORA-06512: at line 1
Das bedeutet also im Umkehrschluss, das INHERIT PRIVILEGES für PUBLIC generell keine gute Idee sind. Dieses Recht sollte nur gezielt vergeben werden. Andernfalls könnte jeder PL/SQL Programmteil, der mit Invoker Rights ausgeführt wird, ein potentielles Sicherheitsrisiko darstellen.
In diesem Beispiel haben wir verdeutlicht, was passieren kann, wenn der Aufrufende mehr Berechtigungen besitzt als der Ersteller. Aber auch der umgekehrte Fall ist möglich, diesen Fall werden wir in einem späteren Blogbeitrag beleuchten.
Kommentare
Keine Kommentare