O SQL Firewall é um recurso que foi introduzido na versão 23ai do Oracle Database (aqui você pode conferir as New features desse release) e como o nome já diz, ele atual como um Firewall para comandos SQL tendo como principal vantagem estar integrado diretamente no banco de dados (diferente de outras abordagens que precisam de um servidor dedicado para isso), nesse post abordo suas principais carateristicas e como realizar uma configuração básica de bloqueio, para isso estou usando o Oracle Database 23ai Free (23.5.0.24.07) e tenho um usuário chamado Tanaka onde as regras serão aplicadas.
O primeiro passo é verificar o status e ativar caso ainda não esteja ativo:
select status from dba_sql_firewall_status;
exec dbms_sql_firewall.enable; -- Para ativar
exec dbms_sql_firewall.enable; -- Para desativar
Ele pode ser ativado tanto a nível de CDB quando de PDB.
Todo o gerenciamento do SQL Firewall é feito usando a package DBMS_SQL_FIREWALL e seu fluxo de uso é basicamente: Ativar(dbms_sql_firewall.enable) -> Monitorar comandos (dbms_sql_firewall.create_capture) -> Configurar as regras de permissão (dbms_sql_firewall.enable_allow_list) , além disso possuímos tabelas e views que nos dão suporte ao registro do que acontece e das configurações ativas.
Com o recurso ativo, podemos iniciar a nossa captura (que é baseada em um usuário) com o seguinte comando:
begin
dbms_sql_firewall.create_capture (
username => 'TANAKA',
top_level_only => true,
start_capture => true);
end;
/
Importante: definindo top_level_only para TRUE realiza apenas a captura de comandos SQL, caso queira capturar PL/SQL você precisa definir como FALSE.
Agora é esperar os comandos de sua aplicação serem executados no banco para que tenhamos uma massa de dados para a configuração das permissões, aqui irei simular alguns comandos e acesso de diferentes IPs.
Podemos consultar os comandos que foram executados e sessões usando as visões dba_sql_firewall_capture_logs e dba_sql_firewall_session_logs respectivamente, entendendo os conteudo dessas duas visões vai nos ajudar a montar as regras do nosso ambiente que podem ser baseadas em:
- IP(dbms_sql_firewall.ip_address)
- Usuário do sistema operacional(dbms_sql_firewall.os_username)
- Programa(dbms_sql_firewall.os_program)
Criando uma liberação/Bloqueio
O ideal é que você execute a captura por diversos dias para não correr o risco de deixar algum comando SQL de fora pois ele só vai permitir a execução de SQLs que foram capturados.
begin
dbms_sql_firewall.enable_allow_list (
username => 'TANAKA',
enforce => dbms_sql_firewall.enforce_all,
block => true);
end;
/
O enforce controla qual o tipo de liberação/bloqueio que será aplicada, ela pode ser baseado em context(username, program ou IP) ou SQL, aqui vamos colocar enforce_all para que cubra tudo.
Agora iremos executar alguns selects para analisar o que capturamos, vamos começar com a dba_sql_firewall_allowed_ip_addr, para acharmos os ips de origem da conexão a dica aqui é filtrar pelo usuário (where username=’user’):

Se fizermos um select na dba_sql_firewall_capture_logs podemos identificar os comandos e mais detalhes como por exemplo a origem do comando e o programa:

Se eu tentar executar um comando fora do que foi capturado irei receber o erro ORA-47605:

Agora se executo um comando que foi capturado a execução ocorre sem problemas:

Bloqueando ou adicionando comandos SQL
Imagine que depois de implementado o allow list, você precise editar o seu conteudo, para realizar o bloqueio você pode:
Executar um select na DBA_SQL_FIREWALL_ALLOWED_SQL e identificar o ALLOWED_SQL_ID que deseja bloquear, nela você pode tentar filtrar pelo username e o campo SQL_TEXT:

E com o ALLOWED_SQL_ID você pode realizar o bloqueio:

E caso eu tente o mesmo comando que estava funcionando:

Para adicionar o comando de volta na lista de permissão você pode consultar a DBA_SQL_FIREWALL_VIOLATIONS buscando o comando:

E usando DBMS_SQL_FIREWALL.APPEND_ALLOW_LIST_SINGLE_SQL passando o SQL_SIGNATURE e o source como DBMS_SQL_FIREWALL.VIOLATION_LOG (de onde estamos buscando essa info), você consegue voltar a liberar o comando:


Para fazer o controle por IP a ideia é a mesma mas nesse caso vamos usar o ADD/DELETE_ALLOWED_CONTEXT
Para bloquear um IP:
BEGIN
DBMS_SQL_FIREWALL.DELETE_ALLOWED_CONTEXT (
username => 'TANAKA',
context_type => DBMS_SQL_FIREWALL.IP_ADDRESS,
value => '192.168.56.1'
);
END;
/
Caso eu tente conectar no banco:

Você pode consultar os ips permitidos na visão DBA_SQL_FIREWALL_ALLOWED_IP_ADDR e caso precise identificar acessos bloqueados você pode ir na DBA_SQL_FIREWALL_VIOLATIONS usando o COMMAND_TYPE=’CONNECT’:

E para voltar a permitir o acesso desse IP:

E posso confirmar na DBA_SQL_FIREWALL_ALLOWED_IP_ADDR que ele está liberado:

Acredito que com essas instruções você já seja capaz de implementar os recursos básicos do SQL Firewall na versão 23ai do Oracle Database, caso tenha alguma dúvida ou tenha encontrado algum problema, sinta-se a vontade para deixar um comentário.