DBMS_SQL_FIREWALL - Firewall dentro da Base de Dados (Parte II)
Para gerar actividade vou usar uns quantos comandos de sql simples a serem executados numa ou mais sessões do utilizador HR.
select * from hr.employees;
select employee_id, first_name, salary from hr.employees;
select * from hr.departments;
select department_name, manager_id from hr.departments;
select count(*) from sh.sales;
Estes comandos incidem em tabelas do utilizador HR, mas também numa do utilizador SH sobre a qual o HR tem privilégios de leitura.
Depois de executar este comandos numa sessão do utilizador HR, abrimos uma sessão do utilizador FWALLADMIN, que é o administrador do SQL_Firewall e vamos validar o que foi capturado através da view dba_sql_firewall_capture_logs.
SQL> select * from dba_sql_firewall_capture_logs;
USERNAME SESSION_ID COMMAND_TYPE SQL_SIGNATURE SQL_TEXT ACCESSED_OBJECTS CURRENT_USER TOP_LEVEL CLIENT_PROGRAM OS_USER IP_ADDRESS
___________ ______________________ ________________ ___________________________________________________________________ ________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ ______________________________________________________________________________ _______________ ____________ _________________________________________ __________ _____________
HR 7289077817488179201 SELECT 2B5A29374C5DAD4C03A4ACB515B5C5A0F709C94C65E1D2F16C3173CE06A0645D SELECT * FROM HR.EMPLOYEES "HR"."EMPLOYEES" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 SELECT 2011BF62397E8CA5968B5C94F50CEF7C68128F364BC657F26F8882C45A133385 SELECT PARAMETER,VALUE FROM NLS_SESSION_PARAMETERS UNION ALL SELECT :"SYS_B_0" NAME,DBTIMEZONE VALUE FROM DUAL UNION ALL SELECT :"SYS_B_1" NAME,SESSIONTIMEZONE VALUE FROM DUAL UNION ALL SELECT :"SYS_B_2" NAME,TZ_OFFSET (SESSIONTIMEZONE) VALUE FROM DUAL UNION ALL SELECT PARAMETER,VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER=:"SYS_B_3" "SYS"."DUAL","SYS"."NLS_DATABASE_PARAMETERS","SYS"."NLS_SESSION_PARAMETERS" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 SELECT 866DB429E294842028A1EA0F759964C4DC32B366B076CD97CCB854C2BF25087B SELECT COUNT (*) FROM SH.SALES "SH"."SALES" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 ALTER SESSION 9E07ABB1F357A5EA3DE06FB201279B146E6CE47393427B0A75ED597340DE667D ALTER SESSION SET TIME_ZONE=? HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 SELECT 17E0C4CE47C80E33907172368677F9872B81C7FBC4713F0011A2F6E74593185C SELECT DBTIMEZONE FROM DUAL "SYS"."DUAL" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 SELECT 02686876388A62D88B13542399B807D87A1AF2E2C3FC13658102F0D4DA73F341 SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM HR.EMPLOYEES "HR"."EMPLOYEES" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 SELECT A10C4C359513461BC58A0C2B57DB210861D6CF80A0F04E3EA7F408C3255660C0 SELECT * FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
HR 7289077817488179201 SELECT 35E7370B8C39D3041A4BAB9B83E4801FAB7AF2B162B116C20789705B8B728708 SELECT DEPARTMENT_NAME,MANAGER_ID FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y java@localhost.localdomain (TNS V1-V3) oracle 127.0.0.1
De notar que foram capturados não apenas o SQL executado explicitamente, mas também o executado implicitamente ao ser feito login. Além dessa informação é também capturado o IP, o OSUSER e o PROGRAM que foi usado para executar o SQL. Veremos num próximo texto que estes são os contextos com os quais poderemos também criar restrições
Os registos demoram uns segundos a aparecer nesta view. Num primeiro instante estarão apenas num buffer que faz o flush depois de algum tempo. Poderemos antecipar esse flush usando o procedimento flush_logs.
SQL> exec dbms_sql_firewall.flush_logs;
A captura deve ser mantida durante o tempo suficiente para que sejam capturados todos os comandos de SQL que este utilizador precisa usar. Depois de activado o firewall ele apenas poderá usar os comandos capturados. Poderemos sempre acrescentar ou remover mais comandos se assim for necessário.
Findo o tempo necessário para a captura, devemos parar a mesma com o procedimento stop_capture.
SQL> exec dbms_sql_firewall.stop_capture('HR');
A partir da captura existente, poderemos então criar a lista de comandos de SQL que poderão ser executados pelo user HR. Essa tarefa será feita usando o procedimento generate_allow_list.
SQL> exec dbms_sql_firewall.generate_allow_list('HR');
SQL> select * from dba_sql_firewall_allow_lists;
USERNAME GENERATED_ON STATUS STATUS_UPDATED_ON TOP_LEVEL_ONLY ENFORCE BLOCK
___________ ___________________________________ ___________ ___________________________________ _________________ ______________ ________
HR 12-OCT-23 14.44.16.122975000 GMT DISABLED 12-OCT-23 14.44.16.122975000 GMT Y ENFORCE_ALL N
Através da consulta à view DBA_SQL_FIREWALL_ALLOW_LISTS conseguimos perceber que a lista foi criada mas ainda não está activa, o seu status está a disabled.
Poderei ver o seu conteudo através da view DBA_SQL_FIREWALL_ALLOWED_SQL.
SQL> select * from dba_sql_firewall_allowed_sql;
USERNAME ALLOWED_SQL_ID SQL_SIGNATURE SQL_TEXT ACCESSED_OBJECTS CURRENT_USER TOP_LEVEL VERSION
___________ _________________ ___________________________________________________________________ ________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ ______________________________________________________________________________ _______________ ____________ __________
HR 8 866DB429E294842028A1EA0F759964C4DC32B366B076CD97CCB854C2BF25087B SELECT COUNT (*) FROM SH.SALES "SH"."SALES" HR Y 1
HR 2 9E07ABB1F357A5EA3DE06FB201279B146E6CE47393427B0A75ED597340DE667D ALTER SESSION SET TIME_ZONE=? HR Y 1
HR 1 2011BF62397E8CA5968B5C94F50CEF7C68128F364BC657F26F8882C45A133385 SELECT PARAMETER,VALUE FROM NLS_SESSION_PARAMETERS UNION ALL SELECT :"SYS_B_0" NAME,DBTIMEZONE VALUE FROM DUAL UNION ALL SELECT :"SYS_B_1" NAME,SESSIONTIMEZONE VALUE FROM DUAL UNION ALL SELECT :"SYS_B_2" NAME,TZ_OFFSET (SESSIONTIMEZONE) VALUE FROM DUAL UNION ALL SELECT PARAMETER,VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER=:"SYS_B_3" "SYS"."DUAL","SYS"."NLS_DATABASE_PARAMETERS","SYS"."NLS_SESSION_PARAMETERS" HR Y 1
HR 3 17E0C4CE47C80E33907172368677F9872B81C7FBC4713F0011A2F6E74593185C SELECT DBTIMEZONE FROM DUAL "SYS"."DUAL" HR Y 1
HR 4 2B5A29374C5DAD4C03A4ACB515B5C5A0F709C94C65E1D2F16C3173CE06A0645D SELECT * FROM HR.EMPLOYEES "HR"."EMPLOYEES" HR Y 1
HR 7 35E7370B8C39D3041A4BAB9B83E4801FAB7AF2B162B116C20789705B8B728708 SELECT DEPARTMENT_NAME,MANAGER_ID FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y 1
HR 5 02686876388A62D88B13542399B807D87A1AF2E2C3FC13658102F0D4DA73F341 SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM HR.EMPLOYEES "HR"."EMPLOYEES" HR Y 1
HR 6 A10C4C359513461BC58A0C2B57DB210861D6CF80A0F04E3EA7F408C3255660C0 SELECT * FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y 1
Tendo a lista de SQL autorizado gerada, o passo seguinte será activar a lista fazendo com que a partir desse momento qualquer sessão do utilizador HR apenas poderá executar o SQL contido nesta lista.
SQL> exec dbms_sql_firewall.enable_allow_list(username => 'HR',enforce => dbms_sql_firewall.enforce_all, block => true);
O procedimento enable_allow_list tem como parâmetros o nome do utilizador da captura, o que queremos validar (no caso vamos validar tudo através da constante dbms_sql_firewall.enforce_all mas poderiamos validar apenas o SQL ou apenas os contextos com IP ou OSUSER. Voltarei a este tema num próximo texto), podemos ainda com o terceiro parâmetro definir se apenas queremos gerar informação sobre SQL não autorizado (false) ou se queremos que seja bloqueado (true).
Se consultarmos a informação sobre a allow_list vemos que neste momento já está activada, bem como todas as suas caracteristicas.
SQL> select * from DBA_SQL_FIREWALL_ALLOW_LISTS;
USERNAME GENERATED_ON STATUS STATUS_UPDATED_ON TOP_LEVEL_ONLY ENFORCE BLOCK
___________ ___________________________________ __________ ___________________________________ _________________ ______________ ________
HR 12-OCT-23 14.44.16.122975000 GMT ENABLED 12-OCT-23 14.50.34.621179000 GMT Y ENFORCE_ALL Y
Agora podemos testar a firewall e se ela está a funcionar como pretendido.
Vamos executar SQL que existe na lista e veremos que é executado sem qualquer problema. SQL fora da lista será bloqueado e enviará uma mensagem de erro significativa.
Vamos iniciar uma sessão com o utilizador HR e executar uns quantos comandos.
SQL> select count(*) from sh.sales;
COUNT(*)
___________
918843
SQL> select * from sh.sales;
Error starting at line : 1 in command -
select * from sh.sales
Error at Command Line : 1 Column : 1
Error report -
SQL Error: ORA-47605: SQL Firewall violation
Ao tentar executar uma query não existente na lista, obtem o erro ORA-47605: SQL Firewall violation.
SQL> select department_name, manager_id from hr.departments;
DEPARTMENT_NAME MANAGER_ID
_______________________ _____________
Administration 200
Marketing 201
Purchasing 114
Human Resources 203
Shipping 121
IT 103
Public Relations 204
Sales 145
Executive 100
Finance 108
Accounting 205
...
SQL> select manager_id, department_name from hr.departments;
Error starting at line : 1 in command -
select manager_id, department_name from hr.departments
Error at Command Line : 1 Column : 1
Error report -
SQL Error: ORA-47605: SQL Firewall violation
De notar que bastou alterar a ordem das colunas para deixar de ser possível ao HR executar um query sobre a sua tabela departments.
É o texto do SQL que é comparado, se for igual executa se for diferente bloqueia. Se tivesse omitido o nome do schema teria sido bloqueado também (hr.employees vs employees)
Apesar de ser owner das tabelas, o utilizador HR só poderá executar os comandos na allowed list. Se tentar fazer insert numa sua tabela será na mesma bloqueado.
SQL> insert into hr.regions values (5,'Região 5');
Error starting at line : 1 in command -
insert into hr.regions values (5,'Região 5')
Error at Command Line : 1 Column : 1
Error report -
SQL Error: ORA-47605: SQL Firewall violation
Atenção que apesar deste comportamento não devo usar o SQL Firewall para restringir acesso a objectos. Para isso existem todos os outros mecanismos de segurança (permissões, roles, etc) que devo usar como forma de assegurar o acesso aos objectos.
O SQL Firewall deve ser usado em conjunto e não como um substituto dessas opções de controlo de acesso. Um dos seus principais objectivos será evitar ataques de SQL injection.
Em simultâneo com os erros na sessão que executa os comandos, são registadas estas violações em tabelas do sistema que poderão ser consultadas através da view DBA_SQL_FIREWALL_VIOLATIONS.
SQL> select * from dba_sql_firewall_violations;
USERNAME COMMAND_TYPE SQL_SIGNATURE SQL_TEXT ACCESSED_OBJECTS CURRENT_USER TOP_LEVEL IP_ADDRESS CLIENT_PROGRAM OS_USER CAUSE FIREWALL_ACTION OCCURRED_AT
___________ _______________ ___________________________________________________________________ ___________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ _____________________ _______________ ____________ _____________ _________________________________________ __________ ________________ __________________ ___________________________________
HR SELECT C0BE0C02034D249309DD8F99248C077F068354E64C6B40949B324366E2944377 SELECT MANAGER_ID,DEPARTMENT_NAME FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.08.04.355133000 GMT
HR SELECT 255FEC30D83F19387FF66F7722C32D9CA224536CB2D26B5F0B1DEBA1019A0E7C SELECT * FROM SH.SALES "SH"."SALES" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 14.50.52.392855000 GMT
HR SELECT 255FEC30D83F19387FF66F7722C32D9CA224536CB2D26B5F0B1DEBA1019A0E7C SELECT * FROM SH.SALES "SH"."SALES" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.06.18.624583000 GMT
HR EXECUTE 506EECAB62FC7FAD2B0E80BF64379BA3A4ABFA615AF1D776C75A78666A8455CF DECLARE L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR; L_STATUS INTEGER DEFAULT -?; INSQLSIX VARCHAR2 (?); BEGIN INSQLSIX :=UPPER (SUBSTR (LTRIM (:1),?,?)); IF ((INSQLSIX IN (?,?,?,?)) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?)) THEN BEGIN L_STATUS :=-?; DBMS_SQL.PARSE (L_THECURSOR,:2,DBMS_SQL.NATIVE); EXCEPTION WHEN OTHERS THEN L_STATUS :=DBMS_SQL.LAST_ERROR_POSITION; END; DBMS_SQL.CLOSE_CURSOR (L_THECURSOR); END IF; :3 :=L_STATUS; END; "SYS"."DBMS_SQL" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.08.04.362672000 GMT
HR EXECUTE 506EECAB62FC7FAD2B0E80BF64379BA3A4ABFA615AF1D776C75A78666A8455CF DECLARE L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR; L_STATUS INTEGER DEFAULT -?; INSQLSIX VARCHAR2 (?); BEGIN INSQLSIX :=UPPER (SUBSTR (LTRIM (:1),?,?)); IF ((INSQLSIX IN (?,?,?,?)) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?)) THEN BEGIN L_STATUS :=-?; DBMS_SQL.PARSE (L_THECURSOR,:2,DBMS_SQL.NATIVE); EXCEPTION WHEN OTHERS THEN L_STATUS :=DBMS_SQL.LAST_ERROR_POSITION; END; DBMS_SQL.CLOSE_CURSOR (L_THECURSOR); END IF; :3 :=L_STATUS; END; "SYS"."DBMS_SQL" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.15.00.474933000 GMT
HR EXECUTE 506EECAB62FC7FAD2B0E80BF64379BA3A4ABFA615AF1D776C75A78666A8455CF DECLARE L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR; L_STATUS INTEGER DEFAULT -?; INSQLSIX VARCHAR2 (?); BEGIN INSQLSIX :=UPPER (SUBSTR (LTRIM (:1),?,?)); IF ((INSQLSIX IN (?,?,?,?)) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?)) THEN BEGIN L_STATUS :=-?; DBMS_SQL.PARSE (L_THECURSOR,:2,DBMS_SQL.NATIVE); EXCEPTION WHEN OTHERS THEN L_STATUS :=DBMS_SQL.LAST_ERROR_POSITION; END; DBMS_SQL.CLOSE_CURSOR (L_THECURSOR); END IF; :3 :=L_STATUS; END; "SYS"."DBMS_SQL" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 14.50.52.481771000 GMT
HR EXECUTE 506EECAB62FC7FAD2B0E80BF64379BA3A4ABFA615AF1D776C75A78666A8455CF DECLARE L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR; L_STATUS INTEGER DEFAULT -?; INSQLSIX VARCHAR2 (?); BEGIN INSQLSIX :=UPPER (SUBSTR (LTRIM (:1),?,?)); IF ((INSQLSIX IN (?,?,?,?)) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?)) THEN BEGIN L_STATUS :=-?; DBMS_SQL.PARSE (L_THECURSOR,:2,DBMS_SQL.NATIVE); EXCEPTION WHEN OTHERS THEN L_STATUS :=DBMS_SQL.LAST_ERROR_POSITION; END; DBMS_SQL.CLOSE_CURSOR (L_THECURSOR); END IF; :3 :=L_STATUS; END; "SYS"."DBMS_SQL" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.06.18.634941000 GMT
HR SELECT 46E496E8C056DCBD6727BBA3813688B6B833C2CCBF10DF2D06007E32ADE1555F SELECT * FROM V$VERSION WHERE BANNER LIKE :"SYS_B_0" "SYS"."V_$VERSION" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 14.50.52.469393000 GMT
HR SELECT 46E496E8C056DCBD6727BBA3813688B6B833C2CCBF10DF2D06007E32ADE1555F SELECT * FROM V$VERSION WHERE BANNER LIKE :"SYS_B_0" "SYS"."V_$VERSION" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.06.18.633488000 GMT
HR INSERT F789C4B0661E70C959474190F4BA262A92B0BDB10D695DB2158C24A3FC38917A INSERT INTO HR.REGIONS VALUES (:"SYS_B_0",:"SYS_B_1") "HR"."REGIONS" HR Y 127.0.0.1 java@localhost.localdomain (TNS V1-V3) oracle SQL violation Blocked 12-OCT-23 15.15.00.463879000 GMT
Podemos verificar quais as violações, de que tipo e todas as suas caracteristicas.
Podemos sempre alterar a lista de SQL autorizado. Poderemos desactivar as listas temporariamente, fazer uma nova captura e acrescentar os novos comandos da nova captura na lista actual. Isso poderá ser feito com o procedimento append_allow_list.
Poderei fazer append a partir da uma nova captura, da lista de violações ou das duas em simultâneo.
No exemplo seguinte, utilizo a lista de violações para acrescentar novos comandos à lista de SQL autorizado.
SQL> exec dbms_sql_firewall.append_allow_list(username => 'HR',source => dbms_sql_firewall.violation_log);
SQL> select * from dba_sql_firewall_allowed_sql;
USERNAME ALLOWED_SQL_ID SQL_SIGNATURE SQL_TEXT ACCESSED_OBJECTS CURRENT_USER TOP_LEVEL VERSION
___________ _________________ ___________________________________________________________________ ___________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ ______________________________________________________________________________ _______________ ____________ __________
HR 9 C0BE0C02034D249309DD8F99248C077F068354E64C6B40949B324366E2944377 SELECT MANAGER_ID,DEPARTMENT_NAME FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y 2
HR 14 255FEC30D83F19387FF66F7722C32D9CA224536CB2D26B5F0B1DEBA1019A0E7C SELECT * FROM SH.SALES "SH"."SALES" HR Y 2
HR 12 7845363265598E2DFF002151F18FACDF9E8073B52E0DF6DC63DC1C8AF8632DEA SELECT TABLE_NAME FROM USER_TABLES "SYS"."USER_TABLES" HR Y 2
HR 4 2B5A29374C5DAD4C03A4ACB515B5C5A0F709C94C65E1D2F16C3173CE06A0645D SELECT * FROM HR.EMPLOYEES "HR"."EMPLOYEES" HR Y 1
HR 1 2011BF62397E8CA5968B5C94F50CEF7C68128F364BC657F26F8882C45A133385 SELECT PARAMETER,VALUE FROM NLS_SESSION_PARAMETERS UNION ALL SELECT :"SYS_B_0" NAME,DBTIMEZONE VALUE FROM DUAL UNION ALL SELECT :"SYS_B_1" NAME,SESSIONTIMEZONE VALUE FROM DUAL UNION ALL SELECT :"SYS_B_2" NAME,TZ_OFFSET (SESSIONTIMEZONE) VALUE FROM DUAL UNION ALL SELECT PARAMETER,VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER=:"SYS_B_3" "SYS"."DUAL","SYS"."NLS_DATABASE_PARAMETERS","SYS"."NLS_SESSION_PARAMETERS" HR Y 1
HR 8 866DB429E294842028A1EA0F759964C4DC32B366B076CD97CCB854C2BF25087B SELECT COUNT (*) FROM SH.SALES "SH"."SALES" HR Y 1
HR 10 506EECAB62FC7FAD2B0E80BF64379BA3A4ABFA615AF1D776C75A78666A8455CF DECLARE L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR; L_STATUS INTEGER DEFAULT -?; INSQLSIX VARCHAR2 (?); BEGIN INSQLSIX :=UPPER (SUBSTR (LTRIM (:1),?,?)); IF ((INSQLSIX IN (?,?,?,?)) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?) OR (SUBSTR (INSQLSIX,?,?)=?)) THEN BEGIN L_STATUS :=-?; DBMS_SQL.PARSE (L_THECURSOR,:2,DBMS_SQL.NATIVE); EXCEPTION WHEN OTHERS THEN L_STATUS :=DBMS_SQL.LAST_ERROR_POSITION; END; DBMS_SQL.CLOSE_CURSOR (L_THECURSOR); END IF; :3 :=L_STATUS; END; "SYS"."DBMS_SQL" HR Y 2
HR 13 46E496E8C056DCBD6727BBA3813688B6B833C2CCBF10DF2D06007E32ADE1555F SELECT * FROM V$VERSION WHERE BANNER LIKE :"SYS_B_0" "SYS"."V_$VERSION" HR Y 2
HR 11 F789C4B0661E70C959474190F4BA262A92B0BDB10D695DB2158C24A3FC38917A INSERT INTO HR.REGIONS VALUES (:"SYS_B_0",:"SYS_B_1") "HR"."REGIONS" HR Y 2
HR 2 9E07ABB1F357A5EA3DE06FB201279B146E6CE47393427B0A75ED597340DE667D ALTER SESSION SET TIME_ZONE=? HR Y 1
HR 3 17E0C4CE47C80E33907172368677F9872B81C7FBC4713F0011A2F6E74593185C SELECT DBTIMEZONE FROM DUAL "SYS"."DUAL" HR Y 1
HR 5 02686876388A62D88B13542399B807D87A1AF2E2C3FC13658102F0D4DA73F341 SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM HR.EMPLOYEES "HR"."EMPLOYEES" HR Y 1
HR 6 A10C4C359513461BC58A0C2B57DB210861D6CF80A0F04E3EA7F408C3255660C0 SELECT * FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y 1
HR 7 35E7370B8C39D3041A4BAB9B83E4801FAB7AF2B162B116C20789705B8B728708 SELECT DEPARTMENT_NAME,MANAGER_ID FROM HR.DEPARTMENTS "HR"."DEPARTMENTS" HR Y 1
A partir deste momento se voltarmos à sessão do utilizador HR poderemos fazer o insert que tinhamos tentado sem sucesso anteriormente.
SQL> insert into hr.regions values (5,'Região 5');
1 row inserted.
Através das listas de comandos conseguimos evitar a utilização de comandos de SQL por parte do utilizador HR. Podemos no entanto ir além do sql e usar os outros contextos que são capturados como o endereço IP, o user do SO e o programa a partir do qual foram executados os SQL capturados.
Falarei dessas opções num futuro post.
Comentários
Enviar um comentário