Utenti proxy per autenticarsi su Oracle
Introduzione
Mi capita spesso che mi chiedano di creare utenze individuali in grado di agire su più schemi e sono quindi costretto a fornire permessi potenzialmente dannosi, tipo il ‘drop any table‘.
Questo perché, altrimenti, dovrei fornire permessi puntuali sugli oggetti (es. tutte permettere a ‘jane‘ di accedere in lettura e modifica a tutte le tabelle dello schema ‘john‘), compresi quelli creati successivamente.
Laboratorio
Di seguito propongo un case study sul pericolo nel concedere determinati permessi.
SQL> conn / as sysdba
Connected.
SQL> CREATE TABLE sys.dummy (id NUMBER);
Table created.
SQL> CREATE TABLE system.dummy (id NUMBER);
Table created.
SQL> CREATE USER jane IDENTIFIED BY "doe"
2 DEFAULT TABLESPACE users
3 TEMPORARY TABLESPACE temp
4 ACCOUNT UNLOCK;
User created.
SQL> GRANT CREATE SESSION TO jane;
Grant succeeded.
SQL> GRANT SELECT ANY TABLE TO jane;
Grant succeeded.
SQL> GRANT DROP ANY TABLE TO jane;
Grant succeeded.
SQL>
Per il test, ho creato una tabella sullo schema ‘sys‘ e una sullo schema ‘system‘.
Ora mi collego con l’utenza ‘jane‘ appena creata e provo a cancellarle.
SQL> conn jane/doe
Connected.
SQL> DROP TABLE sys.dummy;
DROP TABLE sys.dummy
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> SELECT * FROM sys.dummy;
SELECT * FROM sys.dummy
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> SELECT * FROM system.dummy;
no rows selected
SQL> DROP TABLE system.dummy;
Table dropped.
SQL>
Come abbiamo visto, l’utente ‘sys‘ è protetto, per fortuna, ma non possiamo dire la stessa cosa per gli altri account, anche di sistema.
Per ovviare a tale problema e venire comunque incontro alle richieste degli utenti di poter accedere ad altri schemi, possiamo sfruttare una caratteristica poco conosciuta ed introdotta con la versione 9i da Oracle, ovvero la proxy authentication.
SQL> conn / as sysdba
Connected.
SQL> REVOKE DROP ANY TABLE FROM jane;
Revoke succeeded.
SQL> CREATE USER john IDENTIFIED BY "doe"
2 DEFAULT TABLESPACE users
3 TEMPORARY TABLESPACE temp
4 ACCOUNT UNLOCK;
User created.
SQL> GRANT CREATE SESSION TO john;
Grant succeeded.
SQL> GRANT RESOURCE TO john;
Grant succeeded.
SQL> ALTER USER john QUOTA UNLIMITED ON users;
User altered.
SQL> CREATE TABLE john.dummy (id NUMBER);
Table created.
SQL> ALTER USER john GRANT CONNECT THROUGH jane;
User altered.
SQL> show parameter audit
NAME TYPE VALUE
------------------------------------ -------------------------------- --------------------------------
audit_file_dest string /u01/app/oracle/admin/orcl/adump
audit_sys_operations boolean TRUE
audit_syslog_level string
audit_trail string DB
unified_audit_sga_queue_size integer 1048576
SQL> AUDIT SESSION BY jane;
Audit succeeded.
SQL>
Abbiamo creato lo schema ‘john‘ e abbiamo concesso a ‘jane‘ il permesso di collegarsi tramite proxy authentication, così da operare a tutti gli effetti come fosse ‘john‘.
Abbiamo anche verificato l’audit per l’utente ‘jane‘ (vedremo dopo il suo utilizzo).
Come vediamo sotto, se ‘jane‘ si collega normalmente, può vedere la tabella, perché ha la grant ‘select any table‘, ma non può eliminarla, avendo tolto la grant ‘drop any table‘.
SQL> conn jane/doe
Connected.
SQL> SELECT * FROM john.dummy;
no rows selected
SQL> DROP TABLE john.dummy;
DROP TABLE john.dummy
*
ERROR at line 1:
ORA-01031: insufficient privileges
SQL>
Soluzione
Sembrerebbe che ci siamo infilati in un ‘cul de sac’, ma non è così..
Ora proviamo ad effettuare il login con la forma ‘SQL> connect user[schema_owner]/password‘ (la password è quella dell’utente, non dello schema su cui vogliamo operare).
SQL> conn jane[john]/doe
Connected.
SQL> show user
USER is "john"
SQL> DROP TABLE dummy;
Table dropped.
SQL>
Un appunto che mi è stato mosso, quando ho proposto questo metodo di accesso, è stato che non sarebbe stato possibile capire “chi fa cosa”, ovvero capire chi, tra ‘john‘ e ‘jane‘, cancellasse una tabella.
Il nostro laboratorio termina con la verifica della tracciabilità delle azioni interrogando la tabella di sistema ‘dba_audit_trail‘.
SQL> conn / as sysdba
Connected.
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'yyyy-mm-dd hh24:mi:ss';
SQL> SET LINES 132 PAGES 60 TRIMS ON
SQL> COL username for a13
SQL> COL proxy_user for a13
SQL> COL obj_name for a13
SQL> COL timestamp for a20
SQL> SELECT a.username,
2 b.username proxy_user,
3 a.obj_name,
4 a.returncode,
5 a.timestamp,
6 a.sessionid,
7 a.proxy_sessionid
8 FROM dba_audit_trail a,
9 dba_audit_trail b
10 WHERE a.action_name = 'DROP TABLE'
11 AND a.proxy_sessionid = b.sessionid
12 AND b.action_name = 'PROXY AUTHENTICATION ONLY'
13 ORDER BY sessionid;
USERNAME PROXY_USER OBJ_NAME RETURNCODE TIMESTAMP SESSIONID PROXY_SESSIONID
------------- ------------- ------------- ---------- -------------------- ---------- ---------------
JOHN JANE DUMMY 0 2018-09-14 14:27:44 295832023 295832022
SQL>
Come si può notare, la self-join ci permette di verificare che la ‘drop table‘ è stata effettuata da ‘jane‘, collegata tramite proxy authentication.