本文介绍如何使用SQL/Protect插件保护数据库防止SQL注入攻击。

背景信息

防止SQL注入攻击通常是数据库应用开发者的责任,数据库管理者的防御能力较小。SQL/Protect插件通过传入的查询请求来判断SQL注入的发生。一旦发现潜在的危险查询,便向数据库管理员报警,并及时阻断查询的执行。

可以防御的SQL注入攻击类型

攻击类型 说明
Unauthorized Relations攻击 表的访问限制功能对于数据库管理员来说是一项繁琐的事情。SQL/Protect插件提供了一个学习模块,动态跟踪一位用户访问的表之间的关联关系。该模块可以在学习模式(leanrn)下主动学习一个用户访问的表集合,当插件进入被动模式(passive)或者主动模式(active)后,便可以根据学习得到的表集合来检查传入查询的合法性。
Utility Commands攻击 在SQL注入攻击中经常会用到一些常用命令,像典型的DDL(Data Definition Language)语句。例如:创建用户定义的函数来访问其他表的数据。SQL/Protect插件能够阻断这些在应用程序中通常不使用的SQL命令的运行。
SQL Tautology攻击 这是最常见的SQL注入攻击方式,通过在WHERE条件中添加true表达式来绕过条件限制,例如:WHERE password = 'x' OR 'x'='x'。攻击者通常使用该技术来试探数据库的缺陷,SQL/Protect插件可以阻断任何使用true表达式的查询语句。
Unbounded DML Statements攻击 Unbounded DML Statements是一类不受条件限制的数据库更新语句,例如:没有WHERE条件的UPDATE/DELETE操作。攻击者通常使用该操作来更新/删除用户的密码库造成DoS攻击。

受保护的角色

受保护角色是指被该插件保护的用户或者组,受保护角色可以由数据库管理员通过SQL/Protect插件指定。该插件支持为不同的角色制定不同级别的SQL注入保护,不同的级别包含不同的攻击类型。

超级用户不可以成为受保护角色。但是受保护的角色可能升级为超级用户,此时,SQL/Protect插件执行以下操作:
  • 受保护的超级用户执行的每条命令都会产生警报信息。
  • 如果SQL/Protect插件运行在主动模式(active),则阻断受保护的超级用户执行的每个命令。

因此,当SQL/Protect插件运行时,一个受保护的拥有超级用户权限的角色,或者被修改为普通用户,或者将其还原为不受保护的角色。

另外,受保护角色执行的每一个命令都会被记录到一个统计视图中,该视图可以用于识别一个潜在攻击的开始。统计数据收集后,按照不同的攻击类型进行划分。

说明 数据库默认受保护角色的最大数量max_protected_roles为64、受保护表的最大数量max_protected_relations为1024。

在特定的数据库使用SQL/Protect插件

  1. 管理员修改参数,启用SQL/Protect插件功能。
    set polar_sql_protect.enabled = on; #(默认off)
    set polar_sql_protect.level = passive; #(learn/active/passive三种模式,默认passive)
  2. 管理员创建测试数据库targetdb、测试用户test。
    CREATE DATABASE targetdb;
    CREATE ROLE test;
    GRANT ALL ON DATABASE targetdb TO test;
    ALTER ROLE test LOGIN;
  3. 管理员登录数据库targetdb,创建插件并添加受保护角色。
    CREATE EXTENSION sqlprotect;
    SELECT sqlprotect.protect_role('test');
    查看受保护角色列表。
    SELECT * FROM sqlprotect.list_protected_users;
    SELECT * FROM sqlprotect.polar_sql_protect;
  4. 管理员可以根据需要修改插件运行模式,具体操作如下:

    插件有learn、active、passive三种工作模式,默认为passive,详情参见设置角色的保护模式

    • 管理员修改插件运行模式为learn。
      polar_sql_protect.level = learn; #(learn/active/passive三种模式,默认passive)
      1. 使用test用户登录数据库targetdb,建立测试表company并执行查询、插入语句:
        CREATE TABLE company(name VARCHAR(100), employee_num INT);
        SELECT * FROM company;
        INSERT INTO company VALUES('new', 1);
        SELECT * FROM company;
      2. 管理员查看插件学习到的test用户使用的表信息。
        SELECT * FROM sqlprotect.polar_sql_protect_rel;
        SELECT * FROM sqlprotect.list_protected_rels;
    • 管理员修改插件模式为passive。
      polar_sql_protect.level = passive; #(learn/active/passive三种模式,默认passive)
      1. 使用test用户登录数据库targetdb。
      2. 执行SQL注入语句。
        SELECT * FROM company WHERE 1 = 1;
        DELETE FROM company;
        说明 插件提示非法SQL语句,但是不阻断SQL语句的执行。
    • 管理员修改插件模式为active。
      polar_sql_protect.level = active; #(learn/active/passive三种模式,默认passive)
      1. 使用test用户登录数据库targetdb。
      2. 执行SQL注入语句。
        SELECT * FROM company WHERE 1 = 1;
        DELETE FROM company;
        说明 插件提示非法SQL语句,并且阻断SQL语句的执行。

设置受保护的角色

受保护的角色被存储在表polar_sql_protect中,数据库管理员可以选择需要保护的用户/组,将其添加到该表中。

  • 执行protect_role函数,添加用户到受保护角色列表中。
    SELECT sqlprotect.protect_role('userA');
  • 查询插件学习到的受保护角色的表内容。
    select * from sqlprotect.list_protected_users;
    select * from sqlprotect.polar_sql_protect;
  • 执行unprotect_role函数,可解除某个受保护的角色。
    SELECT sqlprotect.unprotect_role('userA');

设置角色的保护模式

参数polar_sql_protect.level决定了受保护角色的保护模式,一共有三种保护模式:learn、passive和active,默认为passive。
保护模式 说明
learn 可以追踪用户的行为,并记录用户使用的表,用于建立受保护角色期望的行为。
passive 当受保护角色执行非法SQL语句时,进行报警,但不阻断SQL语句的执行,可被用于行为监控。
active 阻断受保护角色的所有非法SQL语句的执行,表现为SQL防火墙在攻击者进行渗透测试时便可以起作用,该模式不仅阻断攻击路径,而且还跟踪查询SQL语句,以便于管理员早于攻击者发现数据库的不足之处。
例如,设置保护模式为active。
 polar_sql_protect.level = active;  #设置保护模式为active

修改表polar_sql_protect的某些字段,可以设置一个角色受保护的内容。

targetdb=# \d sqlprotect.polar_sql_protect;
        Table "sqlprotect.polar_sql_protect"
      Column       |  Type   | Collation | Nullable | Default 
--------------------+---------+-----------+----------+--------- 
dbid               | oid     |           | not null |  
roleid             | oid     |           | not null |  
protect_relations  | boolean |           |          |  
allow_utility_cmds | boolean |           |          |  
allow_tautology    | boolean |           |          |  
allow_empty_dml    | boolean |           |          | 
Indexes: 
   "polar_sql_protect_pkey" PRIMARY KEY, btree (roleid)
例如,设置受保护角色16480的allow_utility_cmds为TRUE,即拦截受保护角色16480执行的Utility Commands攻击SQL。
UPDATE sqlprotect.polar_sql_protect SET allow_utility_cmds = TRUE WHERE roleid = 16480; 

其他功能介绍

  • 关闭SQL/Protect插件功能:
    polar_sql_protect.enabled = off #(默认off)
    polar_sql_protect.level = passive #(learn/active/passive三种模式,默认passive)
  • 查看被拦截的SQL语句的统计信息:
    SELECT * FROM sqlprotect.polar_sql_protect_stats;
  • 删除某位用户的被拦截的SQL语句统计信息:
    SELECT sqlprotect.drop_stats('username');