Pular para o conteúdo principal

Usando bind variables para solucionar problemas de segurança no Oracle



- Sabemos que existe vários casos onde o uso de bind variables pode nos ajudar bastante do ponto de vista da peformance das consultas, mas uma outra área que devemos ter cuidado ao usar binds, é a da segurança de nosso banco. Vou mostrar na prática como o uso de bind pode nos ajudar a dar mais segurança ao código.


- Faço a criação da nossa tabela de testes e depois faço insert de algumas linhas.

create table clientes (pri_nome varchar2(50), ult_nome varchar2(50));

insert into clientes values ('Thiago','Castro');
insert into clientes values ('Lucas','Costa');
insert into clientes values ('João','Souza');
insert into clientes values ('Antônio','Pereira');
commit;

1 row created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
Commit complete.




- Vamos criar uma procedure bem simples, a teste_inject. Como podemos ver no código, ela pega o parâmetro passado, o ultimo nome do cliente, e faz uma contagem na tabela de clientes para saber a quantidade de clientes que tenho com o sobre nome passado.


CREATE OR REPLACE PROCEDURE teste_inject_s_bind (nome in clientes.ult_nome%TYPE) IS
BEGIN
   DECLARE
       texto VARCHAR2(2000);
       contagem NUMBER;
       BEGIN
       texto := 'SELECT COUNT(*) FROM clientes s WHERE s.ult_nome= '''||nome||'''';
       EXECUTE IMMEDIATE texto INTO contagem;
       DBMS_OUTPUT.PUT_LINE ('Quantidade de clientes: '||TO_CHAR(contagem));
       END;
END teste_inject_s_bind;
/

Procedure created.



-  Executei a procedure de duas formas. Na primeira forma, com o comportamento normal do programa e na segunda passei um parâmetro diferente que  alterou o comportamento do código. Sei que nesse exemplo isso não quer dizer muita coisa, mas imaginem se nessa tabela estivessem dados sigilosos.

Abaixo o comportamento da procedure com os dois parâmetros:


Execução 1
SQL> exec teste_inject_s_bind('Castro');
Quantidade de clientes: 1

PL/SQL procedure successfully completed.


Execução 2
SQL> exec teste_inject_s_bind(''' or 1=1--');
Quantidade de clientes: 4

PL/SQL procedure successfully completed.



SQL> SELECT COUNT(*) FROM clientes s WHERE s.ult_nome='' or 1=1--';

  COUNT(*)
----------
     4


   
- Certo sabemos que o código tem uma falha, o que fazer para consertar o problema? Na procedure teste_inject_s_bind se tivéssemos usado binds, evitaríamos esse problema. Então vamos criar uma nova procedure, só que agora com uso de bind.



CREATE OR REPLACE procedure teste_inject_c_bind (nome in clientes.ult_nome%TYPE) IS
BEGIN
   DECLARE 
       texto VARCHAR2(2000);
       contagem NUMBER;
       BEGIN
       texto := 'SELECT COUNT(*) FROM clientes s WHERE s.ult_nome= :p_nome';
       EXECUTE IMMEDIATE texto INTO contagem USING nome;
       DBMS_OUTPUT.PUT_LINE ('Quantidade de clientes: '||TO_CHAR(contagem));
       END;
END teste_inject_c_bind;
/

Procedure created.
   


- Agora vamos executar a nova procedure com os mesmos parâmetros.


1 Execução
SQL> exec teste_inject_c_bind('Castro');
Quantidade de clientes: 1

PL/SQL procedure successfully completed.



2 Execução
SQL> exec teste_inject_c_bind(''' or 1=1--');
Quantidade de clientes: 0

PL/SQL procedure successfully completed.




- Repare que na segunda execução da teste_inject_c_bind, o retorno foi 0, ou seja, o nosso parâmetro para alterar o resultado da consulta não funcionou.

Comentários

Postagens mais visitadas deste blog

Configurando a política de retenção de backups no RMAN

                       Configurando a politica de reten çã o de backups no RMAN        O objetivo deste post é explicar como podemos configurar a reten çã o de backups na poderosa ferramenta de backup do bando de dados Oracle RMAN. Podemos configurar nossa pol í tica tendo por base dois tipos: janela de recupera çã o (recovery window) ou redundãncia (redundancy). Abaixo iremos abordar os dois tipos.       Para identificar qual dos dois tipos o RMAN está usando, use: RMAN> show retention policy; Política baseada em redundância CONFIGURE RETENTION POLICY TO REDUNDANCY 1; Política baseada em janela de recuperação CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 2 DAYS; ·        Política baseada em redund â ncia ( REDUNDANCY )       De uma maneira bem simples e objetiva, o par â metro REDUNDANCY especifica quantos backups full ou incremental level 0 de cada datafile o RMAN vai manter, os demais são considerados obsoletos. Veja o exemplo abaixo

Permissões necessárias para criar triggers no Oracle

Há pouco tempo passei por um problema durante a criação de uma trigger de LOGON na versão 12c do banco de dados Oracle. Estava com alguns problemas em uma aplicação que tinha uma trigger de Logon. A trigger em si era bem simples, vou por o código mais abaixo, o problema é que ela estava criada dentro do usuário SYSTEM. Provavelmente foi a maneira mais fácil e preguiçosa de criar o objeto, uma vez que o SYSTEM já possui todas as permissões necessárias para criação. Porém isso não uma boa prática. Então resolvi tirar do SYSTEM e jogar para o usuário dono dos objetos da aplicação. Quando fui tentar criar o objeto no SCHEMA dono dos objetos da aplicação, recebi um erro com falta de permissões: ORA-01031: insufficient privileges . O erro ocorreu porque estava esquecendo de conceder a role ADMINISTER DATABASE TRIGGER para o usuário. Em resumo, as permissões necessárias para criação de uma trigger: CREATE TRIGGER - para criar uma trigger no seu próprio esquema (SCHEMA) CREATE AN

ORA-01623 ORA-00312 - Removendo redo logs

Após realizar um restore de um ambiente de Oracle RAC para um single instance usando snapshot de storage, tentei recriar os redo logs recebi o seguinte erro durante a exclusão de um grupo de discos. SQL> alter database drop logfile group 2; ORA-01623: o log 2 é o log atual para a instância UOW (thread 1) - não é possível eliminar ORA-00312: thread 2 do log 1 on-line: '+DATA/UOW/ONLINELOG/group_2.1638.1051804433' ORA-00312: thread 2 do log 1 on-line: '+DATA/UOW/ONLINELOG/group_2.981.1051804433' O erro quer dizer que o grupo de redo pertence a outra thread. Quer dizer que ele pertence a outra instância do ambiente RAC. Como no meu caso não precisarei mais dela, basta usar o comando: SAL> alter database disable thread 2; Database altered.   Usei o SQL abaixo para gerar os comandos para excluir os redo logs SQL> select distinct 'alter database drop logfile group '||(group#)||';' from v$log where thread#=2; 'ALTERDATABASEDROPLOGFILEGROUP'||(G