Bootstrap

23C新特性SQL防火墙(SQL Firewall)


一 描述

1.1 SQL防火墙的介绍

SQL防火墙通过监控和阻止未经授权的SQL和SQL注入攻击来工作。它内置了一系列规则,可以识别和阻止常见的SQL注入攻击,如布尔型注入、报错注入、联合查询注入、堆叠查询注入等。此外,它还可以通过基于角色的访问控制(RBAC)来限制用户的访问权限,从而防止SQL注入攻击。
SQL防火墙的优点在于它内置在数据库内部,不需要任何外部组件或代理,因此可以提供更高效和可靠的防护。此外,它可以自动识别和阻止SQL注入攻击,而无需手动配置或更新防火墙规则。

1.2 SQL防火墙的注意事项

• 如果我们基于捕获进行 SQL 防火墙配置,则必须运行捕获足够长的时间才能获取所有可能的变化。假设我们运行捕获一周,然后基于该捕获启用 SQL 防火墙。然后,我们尝试运行一些月度、季度或新增业务语句,它会被阻止,因为它在捕获期间未执行过。
• 应用程序会随着时间的推移而发展,因此新版本可能包含许多新的 SQL 语句,这些语句将被阻止,直到修改 SQL 允许列表。会话上下文允许列表(IP 地址、操作系统用户和操作系统程序)也可能随时间而更改。
• SQL 防火墙的存在并不是放松“最小权限”管理和使用防火墙的传统访问控制的借口。它是对那些应该已经到位的安全层的补充。
• SQL 防火墙可用于监视活动,而不是阻止它。将过程中的参数BLOCKENABLE_ALLOW_LIST设置为 false 意味着它将记录,但不会阻止。
• 可以在根容器或 PDB 中启用 SQL 防火墙。

二 SQL防火墙测试

2.1 创建测试用户

创建用户脚本:

conn sys/SysPassword1@//localhost:1521/freepdb1 as sysdba

drop user if exists fwadmin cascade;

create user fwadmin identified by fwadmin;
grant create session to fwadmin;
grant sql_firewall_admin to fwadmin;


drop user if exists schema_owner cascade;

create user schema_owner identified by schema_owner quota unlimited on users;
grant db_developer_role to schema_owner;


drop user if exists app_user_1 cascade;

create user app_user_1 identified by app_user_1;
grant create session to app_user_1;
grant select any table on schema schema_owner to app_user_1;

创建两张表用于测试

drop table if exists schema_owner.t1 purge;
create table schema_owner.t1 (id number);
insert into schema_owner.t1 values (1);

drop table if exists schema_owner.t2 purge;
create table schema_owner.t2 (id number);
insert into schema_owner.t2 values (2);

commit;

2.2 SQL防火墙抓取(审计)会话

登录防火墙权限用户,开启防火墙

conn fwadmin/fwadmin@//localhost:1521/freepdb1

exec dbms_sql_firewall.enable;

使用以下查询检查 SQL 防火墙的状态。

select status   from  dba_sql_firewall_status;

STATUS
--------
ENABLED

#启用对应用户跟踪日志
begin
  dbms_sql_firewall.create_capture (
    username       => 'app_user_1',
    top_level_only => true,
    start_capture  => true);
end;
/

新建会话使用app_user_1用户连接,执行查询操作

#用sqlplus 连接执行
select * from schema_owner.t1;
select * from schema_owner.t2;

#用pl/sql也登录一个会话,执行同样的操作

select * from schema_owner.t1;
select * from schema_owner.t2;

回到防火墙管理员会话中,查询日志

select command_type,
       current_user,
       client_program,
       os_user,
       ip_address,
       sql_text
from   dba_sql_firewall_capture_logs
where  username = 'APP_USER_1';

COMMAND_TYPE CURRENT_USER    CLIENT_PROGRAM                                OS_USER    IP_ADDRESS SQL_TEXT
------------ --------------- --------------------------------------------- ---------- ---------- ------------------------------
SELECT       APP_USER_1      sqlplus@localhost.localdomain (TNS V1-V3)     oracle     127.0.0.1  SELECT DECODE (USER,:"SYS_B_0"
                                                                                                 ,XS_SYS_CONTEXT (:"SYS_B_1",:"
                                                                                                 SYS_B_2"),USER) FROM SYS.DUAL

SELECT       APP_USER_1      sqlplus@localhost.localdomain (TNS V1-V3)     oracle     127.0.0.1  SELECT * FROM SCHEMA_OWNER.T2
SELECT       APP_USER_1      PL/SQL                                         tim_hall   10.0.2.2   SELECT * FROM SCHEMA_OWNER.T2
SELECT       APP_USER_1      sqlplus@localhost.localdomain (TNS V1-V3)     oracle     127.0.0.1  SELECT * FROM SCHEMA_OWNER.T1
SELECT       APP_USER_1      PL/SQL                                       tim_hall   10.0.2.2   SELECT * FROM SCHEMA_OWNER.T1

SQL>

停止抓取

exec dbms_sql_firewall.stop_capture('app_user_1');

2.3 创建防火墙规则

根据日志为用户生成允许列表。

exec dbms_sql_firewall.generate_allow_list ('app_user_1');

可以通过IP地址、程序、系统用户、SQL语句进行配置规则。

#IP 地址
select *
from   dba_sql_firewall_allowed_ip_addr
where  username = 'APP_USER_1';

USERNAME             IP_ADDRESS
-------------------- ----------
APP_USER_1           10.0.2.2
APP_USER_1           127.0.0.1


#应用程序
select *
from   dba_sql_firewall_allowed_os_prog
where  username = 'APP_USER_1';

USERNAME             OS_PROGRAM
-------------------- --------------------------------------------------
APP_USER_1           PL/SQL
APP_USER_1           sqlplus@localhost.localdomain (TNS V1-V3)

#系统用户
select *
from   dba_sql_firewall_allowed_os_user
where  username = 'APP_USER_1';

USERNAME             OS_USER
-------------------- ----------
APP_USER_1           oracle
APP_USER_1           tim_hall


#SQL语句内容
select current_user,
       sql_text
from   dba_sql_firewall_allowed_sql
where  username = 'APP_USER_1';

CURRENT_USER    SQL_TEXT
--------------- --------------------------------------------------
APP_USER_1      SELECT DECODE (USER,:"SYS_B_0",XS_SYS_CONTEXT (:"S
                YS_B_1",:"SYS_B_2"),USER) FROM SYS.DUAL

APP_USER_1      SELECT * FROM SCHEMA_OWNER.T2
APP_USER_1      SELECT * FROM SCHEMA_OWNER.T1

SQL>

使用以下过程配置允许下列IP地址可进行删除操作。

##添加IP地址
begin
  dbms_sql_firewall.add_allowed_context (
    username     => 'app_user_1',
    context_type => dbms_sql_firewall.ip_address,
    value        => '192.168.56.1');
end;
/


##确认IP列表
column ip_address format a12

select *
from   dba_sql_firewall_allowed_ip_addr
where  username = 'APP_USER_1';

USERNAME             IP_ADDRESS
-------------------- ------------
APP_USER_1           10.0.2.2
APP_USER_1           127.0.0.1
APP_USER_1           192.168.56.1

SQL>


##删除IP地址
begin
  dbms_sql_firewall.delete_allowed_context (
    username     => 'app_user_1',
    context_type => dbms_sql_firewall.ip_address,
    value        => '192.168.56.1');
end;
/


##确认IP列表

select *
from   dba_sql_firewall_allowed_ip_addr
where  username = 'APP_USER_1';

USERNAME             IP_ADDRESS
-------------------- ------------
APP_USER_1           10.0.2.2
APP_USER_1           127.0.0.1

SQL>

下面示例,我们同时启用上下文和 SQL 允许列表。若将参数设置为 false只会记录异常操作,但不会阻止操作。

begin
  dbms_sql_firewall.enable_allow_list (
    username => 'app_user_1',
    enforce  => dbms_sql_firewall.enforce_all,
    block    => true);
end;
/

可以使用视图查看允许列表的状态。DBA_SQL_FIREWALL_ALLOW_LISTS

select username,
       status,
       top_level_only,
       enforce,
       block
from   dba_sql_firewall_allow_lists
where username='APP_USER_1';

USERNAME             STATUS   TOP_LEVEL_ONLY ENFORCE         BLOCK
-------------------- -------- -------------- --------------- --------------
APP_USER_1           ENABLED  Y              ENFORCE_ALL     Y

SQL>

可以使用该视图检查 SQL 防火墙的违规情况。DBA_SQL_FIREWALL_VIOLATIONS

select sql_text,
       firewall_action,
       ip_address,
       cause,
       occurred_at
from   dba_sql_firewall_violations
where  username = 'APP_USER_1';

使用不同的会话,向数据库发出未知和已知的SQL语句。请注意,未知语句失败,并显示“ORA-47605:SQL 防火墙冲突”错误。

-未知语句
select count(*) from schema_owner.t1;

Error starting at line : 1 in command -
select count(*) from schema_owner.t1
Error at Command Line : 1 Column : 1
Error report -
SQL Error: ORA-47605: SQL Firewall violation

SQL>


-- 列表内语句
select * from schema_owner.t1;

  COUNT(*)
----------
         1

SQL>

登录防火墙管理员用户并检查违规行为。

select sql_text,
       firewall_action,
       ip_address,
       cause,
       occurred_at
from   dba_sql_firewall_violations
where  username = 'APP_USER_1'
and    sql_text like '%COUNT%';

SQL_TEXT                                           FIREWAL IP_ADDRESS   CAUSE                OCCURRED_AT
-------------------------------------------------- ------- ------------ -------------------- -----------------------------------
SELECT COUNT (*) FROM SCHEMA_OWNER.T1              Blocked 10.0.2.2     SQL violation        03-JUL-23 09.35.55.318805 PM +00:00

SQL>

如果我们发现应该允许通过的违规行为,我们可以手动将它们添加到允许列表中,也可以通过从日志中提取它们来添加它们。

select count(*) from schema_owner.t1;

  COUNT(*)
----------
         1

SQL>

2.4 sql防火墙相关视图

select view_name
from   dba_views
where  view_name like 'DBA_SQL_FIREWALL%'
order by 1;

VIEW_NAME
--------------------------------------------------------------------------------
DBA_SQL_FIREWALL_ALLOWED_IP_ADDR
DBA_SQL_FIREWALL_ALLOWED_OS_PROG
DBA_SQL_FIREWALL_ALLOWED_OS_USER
DBA_SQL_FIREWALL_ALLOWED_SQL
DBA_SQL_FIREWALL_ALLOW_LISTS
DBA_SQL_FIREWALL_CAPTURES
DBA_SQL_FIREWALL_CAPTURE_LOGS
DBA_SQL_FIREWALL_SESSION_LOGS
DBA_SQL_FIREWALL_SQL_LOGS
DBA_SQL_FIREWALL_STATUS
DBA_SQL_FIREWALL_VIOLATIONS
;