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