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

来源:这里教程网 时间:2026-03-03 19:18:51 作者:

描述                                            

SQL 防火墙 的介绍

SQL 防火墙通过监控和阻止未经授权的SQL SQL 注入攻击来工作。它内置了一系列规则,可以识别和阻止常见的SQL 注入攻击,如布尔型注入、报错注入、联合查询注入、堆叠查询注入等。此外,它还可以通过基于角色的访问控制(RBAC )来限制用户的访问权限,从而防止SQL 注入攻击。

防火墙的优点在于它内置在数据库内部,不需要任何外部组件或代理,因此可以提供更高效和可靠的防护。此外,它可以自动识别和阻止SQL 注入攻击,而无需手动配置或更新防火墙规则。

SQL 防火墙的注意事项

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

    防火墙测试

    创建测试用户

    创建用户脚本:

    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;

    防火墙抓取(审计)会话

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

    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');

    创建防火墙规则

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

    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>

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

    exec dbms_sql_firewall.append_allow_list('app_user_1', dbms_sql_firewall.violation_log);

    尝试再次运行导致冲突的查询,会正常通过

    select count(*) from schema_owner.t1;
     
      COUNT(*)
    ----------
             1
     
    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

  • 相关推荐