EnterpriseDB的SQL注入攻击保护功能一
enterprisedb是基于postgresql的企业级数据库(即PPAS)。
PPAS(Postgres Plus Advanced Server)提供了一种强大的安全机制以防止SQL注入攻击的能力,并将在下详细介绍其功能与实现细节。
a. 概述与功能介绍
b. 配置步骤与参数设置
c. 通常维护操作指南
d. 数据库备份与恢复流程
黑客常用 SQL 注入攻击手段针对数据库实施攻击。伴随着 B/S 模式的应用开发不断深化,越来越多的人开始采用这种编程模式来开发应用程序。然而,由于不同 programmer 的技术水平和经验各有差异,相当一批 programmer 编写代码时忽略了用户输入数据合法性验证,导致系统存在潜在安全隐患。普通用户可向系统提供一段需要执行特定功能的 SQL 语句,通过程序处理后得到相应的结果信息,即常说的 SQL 注入现象。从标准 HTTP/HTTPS 协议下的访问途径来看,这一操作看似与普通 Web 页面访问无明显区别,因此现有的防火墙通常不会触发异常警报关于 SQL 注入问题。然而,由于这一手法灵活性极强,在实际操作中常常会遇到各种意外情况,需要开发者精心设计并构造出巧妙的 SQL 语句才能达到预期目的。
PPAS支持实施SQL注入防护机制。通常情况下,此类防护措施需由应用开发人员负责部署与维护;而数据库管理员则不具备相关能力。PPAS通过对输入的SQL语句进行审查与解析,在运行时自动识别并防止潜在的安全漏洞。
该系统向数据库管理员提示潜在风险查询,并采取措施阻止执行这些查询请求。
这一届专门介绍多种类型的SQL注入攻击及其如何阻止这类潜在的SQL注入威胁。
注
在SQL注入攻击中会经常使用一些常见命令例如典型的DDL语句。例如使用诸如创建用户定义函数的功能来访问系统其他资源。而SQL/Protect则能够阻止这些在应用程序中通常不被使用的SQL命令被执行。通常情况下这些命令不会对应用程序造成影响但一旦被滥用就可能带来安全风险因此需要特别注意和防护措施
c SQL Tautology/ SQL注入技术
在SQL注入攻击中使用最常见的手法是通过WHERE子句增加额外内容。
例如,在WHERE子句中插入如"password = 'x'" 或 " 'x' = 'x'" 的内容。
攻击者往往利用这一点来发现系统中的安全漏洞,并且这类查询会被特定工具如SQL/Protect成功阻塞。
具体的攻击方法可参考我的文章《SQL注入攻击》 1.1.1 被监控的角色 用于监控受保护角色的SQL注入威胁,则需分析其session中的SQL语句。 受保护角色由PPAS数据库管理员选择负责监控的角色(PPAS里将用户与组统称为角色)。 每个被监控的角色均可根据需求选择需关注的注入威胁类型(如前所述),从而实现不同级别的防护措施,并显著降低了DBA管理用户的负担。
注意:
超级用户不能作为受保护的角色。如果受保护的角色后来成了超级用户,该角色的某些行为
将被显示:
a 当这个受保护的superuser的每一个sql命令被SQL/Protect抛一个警告信息。
b 受保护的superuser执行每一个命令,都会在统计信息视图edb_sql_protect_stats中
的superusers列都会加1.
c 当SQL/Protect是active模式时,所有受保护superuser用户执行的命令被禁止运行。
1.1.2
攻击统计:
受保护用户的每一个命令被SQL/Protect当作攻击而记录。这些条件能通过试图访问以
识别攻击的开始。
如果受保护用户连接了多个数据库,这个用户的攻击统计信息分别存放在连接的数据库里。
注意:
数据库运行时SQL/Protect统计信息维护在内存里。数据库停止运行后,这些信息存放在
data/global里面的二进制文件edb_sqlprotect.stat里。
2
配置SQL/Protect功能
为了使SQL/Protect功能正常运行,在PPAS的lib目录中需要安装相应的程序库文件(Linux系统中使用的是sqlprotect.so文件,在Windows系统中则使用sqlprotect.dll文件)。
此外,在share/contrib文件夹中必须存在名为sqlprotect.sql的任务脚本以完成操作。
应确保将数据库服务器上应用SQL/Protect功能,并对每一个需要监控的数据库进行相应的设置。a) 应设置postgresql.conf文件中相关的参数设置;b) 在被监控的数据库中应安装SQL/protect所需的应用对象,并完成必要的配置步骤。
在postgresql.conf文件中进行如下设置:
shared_preload_libraries字段建议添加$libdir/sqlprotect。
为了实现安全机制的增强, 我们需要在custom_variable_classes字段建议新增edb_sql_protect。
是否启用SQL/Protect功能,默认关闭。
为了控制访问权限, 缺省设置为passive模式,默认初始状态为learn策略。
最大保护角色数默认设为64个;每个用户的最大保护关系数默认设为1024个。
shared_preload_libraries = 'libdir/dbms_pipelibdir/edb_genlibdir/plugins/plugin_debuggerlibdir/plugins/plugin_spl_debugger$libdir/sqlprotect' # 要求进行修改需要重新启动
custom_variable_classes = 'dbms_pipe dbms_alert edb_sql_protect' # 定义自定义的变量类名称列表
edb_sql_protect.enabled_off
edb_sql_protect.level_set_to_learn
edb_sql_protect.maxProtectedRoles_set_to_64
edb_sql_protect.maxProtectedRelations_set_to_1024
配置步骤2:
重启数据库
第3步:配置完成后,请作为superuser登录到每个protected数据库,并执行位于 /opt/PostgresPlus/9.1AS/share/contrib中的sqlprotect.sql脚本。该脚本会在模式sqlprotect内创建一个名为db_protections的对象,并在此模式下生成一系列的安全措施来防止未授权访问此对象的所有操作。以下实例展示了在数据库edb中执行此过程:通过以下命令登录edB数据库并运行相应的安全控制程序: /opt/PostgresPlus/9.1AS/bin/psql -d edb -U enterprisedb;随后将返回密码提示;输入enterprisedb后即可进入系统并执行指定的安全操作;之后请确认路径是否正确无误;最后按Ctrl+D退出psql界面;完成以上操作后请重新启动edB服务以确保配置生效
2.1
选择受保护的角色
现在受保护的角色和保护级别。
2.1.1
创建受保护的角色列表
对于每个受保护的数据库,请将监控的角色/用户加入该数据库的受保护角色列表。
步骤一:
启动PostgreSQL服务并连接到指定数据库
$ /opt/PostgresPlus/9.1AS/bin/psql -d edb -U enterprisedb
输入用户enterprisedb的密码:
输入'hel'获取帮助信息。
第二步:
将模式sqlprotect设为查询路径
edb=# SET search_path TO sqlprotect;
SET
--增加-- create user appuser password 'appuser';
步骤三:在表edb_sql_protect中维护受保护的角色,并通过函数protect_role('rolename')来增加角色。新增角色appuser时会触发错误提示:protected user hash not initialized,请确保已初始化后再执行相关操作。执行SELECT命令以验证结果如下:
根据表中的结果进行验证
In the view, validate the results.
Execute the following SQL statement: SELECT * FROM list_protected_users;
-[ RECORD 1 ]------+--------
Database name | Username
appuser | Protect relations
Enabled | Allow utility commands
Disallowed | Allow tautology
Disallowed | Allow empty_dml
第2.1.2节设置保护级别
它所定义的防护等级决定了在该database server上的所有databases中protected users的操作行为
edb_sql_protect.level设置当前为:
learn: 监控受保护用户的活动并记录他们所涉及的表。初始状态即为如此。
passive: 如果受保护的角色违反了定义的规则,则会触发警告但不会中断SQL执行过程。
这是为了使保护角色遵循预期的行为模式而需进行设置。
active:对于受保护的角色将阻止执行所有无效SQL语句。这类似于SQL防火墙的作用范围。
默认情况下设为passive状态;如果第一次使用SQL/Protect功能,则建议将edb_sql_protect.level设为learn。
在配置完SQL/Protect功能、指定受保护用户以及设定相应的保护级别之后,就可以开始运行应用程序了. 确定好需要赋予受保护角色的权限范围之后,接下来就要确保这些角色能够访问相关的数据库表和视图. 在learn模式下,SQL/Protect会将受保护用户的访问记录存储到EDB中的sql_protect_rel表中.
当SQL/Protect在passive或active模式下执行时启动抵御攻击的监控。在该模式下,在其关联的关系中给予角色访问权限以查看受保护的关系。
然而,在这种情况下(即角色试图访问其权限范围外的关系),SQL/Protect将返回一条警告信息或错误提示。此SQL语句的执行结果取决于模式是被动还是主动。
2.2.1
learn模式
步骤1:
已设置相关参数于postgresql.conf文件中。
edb_sql_protect.active = enable
edb_sql_protect.level = learning level
步骤2:
读取postgresql.conf文件
作为超级用户连接到数据库
运行下面指定的函数pg_reload_conf.
EDB=# SELECT pg_reload_conf;
PG_RELOAD_CONF
----------------
T
(1 ROW)
步骤3:
允许受保护用户运行其应用
以受保护角色appuser在psql里运行下面的sql。
edb=> SELECT * FROM dept;
NOTICE: SQLPROTECT: Learned relation: 16384
deptno | dname | loc
--------+------------+----------
10 | ACCOUNTING | NEW YORK
20 | RESEARCH | DALLAS
30 | SALES | CHICAGO
40 | OPERATIONS | BOSTON
(4 rows)
edb=> SELECT empno, ename, job FROM emp WHERE deptno = 10;
NOTICE: SQLPROTECT: Learned relation: 16391
empno | ename | job
-------+--------+-----------
7782 | CLARK | MANAGER
7839 | KING | PRESIDENT
7934 | MILLER | CLERK
(3 rows)
上面的NOTICE指明关系增加到了该用户的受保护关系列表里。
在学习模式中,默认情况下不会阻止怀疑SQL语句的执行,并会发出警告提示(NOTICE)。但可能会对某些操作进行限制以提高安全性。
edb=> CREATE TABLE appuser_tab (f1 INTEGER);
NOTICE: SQLPROTECT: 被禁止用于此用户。
NOTICE: SQLPROTECT: 学习关系中的记录数为16672。
NOTICE: SQLPROTECT: 非法查询:空DML指令。
删除0条记录。
步骤4:
具备权限的应用程序会查询受保护的表以识别并列出增加到该角色的受保护关系列表中的所有关系。
由管理员配置查询路径为模式sqlprotect以便执行监控任务
edb=# SET search_path TO sqlprotect;
SET
在表edb_sql_protect_rel里查看增加到受保护关系列表里的关系:
edb=# SELECT * FROM edb_sql_protect_rel;
dbid | roleid | relid
-------+--------+-------
13917 | 16671 | 16384
13917 | 16671 | 16391
13917 | 16671 | 16672
(3 rows)
在试图list_protected_rels里查看更易于理解的信息
edb=# SELECT * FROM list_protected_rels;
Database | Protected User | Schema | Name | Type | Owner
----------+----------------+--------+-------------+-------+--------------
edb | appuser | public | dept | Table | enterprisedb
edb | appuser | public | emp | Table | enterprisedb
edb | appuser | public | appuser_tab | Table | appuser
(3 rows)
2.2.2
passive模式
用到确定受保护角色的应用已涵盖了所有相关的关联,则可实现权限控制以提高安全性
passive模式是两个保护模式passive和active里不严格的。
步骤1 在postgresql.conf文件中设置以下参数以将SQL/Protect功能设为passive模式:edb_sql_protect.enabled字段设为on状态,并将level字段设为passive状态
步骤二:
导入 PostgreSQL 配置文件
使用 superuser 来连接到数据库
并执行下面的 PostgreSQL 配置文件 reload 函数:
edb=# SELECT pg_restore('your_database_name');
成功恢复 your_database_name 数据库
----------------
成功完成
(1 row)
在appuser环境中执行以下SQL语句,在部门表中查询结果如下:
执行SQL访问不在protected list中的关系或涉及具有潜在风险的SQL指令时,在此用户环境中不会阻止该操作但会触发警告信息
步骤3
监控可疑行为的统计信息
通过执行视图edb_sql_protect_stats能够获取访问未受保护列表的关系以及存在潜在SQL语句的风险次数
执行一次查询操作以检查系统设置
Set the search path to sqlprotect
执行一次SELECT操作以检索表中的记录
Connect to the database and execute a SELECT statement on the edb_sql_protect_stats table
Retrieve and display the statistics for user accounts
The query will return the following columns: username, number of superusers, number of related tables, number of commands executed, number of tautology checks performed, and whether DML operations are allowed
The results indicate that there is one active account with no superusers, three related tables, one command executed in the last interval, one tautology check performed, and DML operations are not allowed for this account
2.2.3 活跃模式 在活跃模式中进行配置时,请确保禁止所有sql语句的执行,并且,在这种情况下会抛出一个错误以替代警告。
步骤1
在postgresql.conf文件中设置相关参数以启用SQL/Protect功能,并将其设为active状态
步骤2 操作如下:
- 获取postgresql.conf文件内容
- 作为超级用户连接至数据库系统
- 运行该函数pg_reload_conf()
- 在edybon环境下运行SELECT pg_reload_conf();
以appuser数据库上执行SQL语句:
edb=> CREATE TABLE appuser_tab_3 (f1 INTEGER);
该操作对当前用户不可行。
edb=> INSERT INTO appuser_tab_2 VALUES (1);
向appuser_tab_2表中插入一行数据。
edb=> SELECT * FROM appuser_tab_2 WHERE 'x' = 'x';
从appuser_tab_2表中查询所有记录,并根据条件'x'等于自身进行筛选。
ERROR: SQLPROTECT:此查询涉及关系对象不可行。
查询统计数据显示
