数据库内核月报 - 2020 / 07

PgSQL · 引擎特性 · SQL防火墙使用说明与内核浅析

背景简介

SQL注入通常是业务层做的事情,例如使用绑定变量,使用关键字过滤等手段,避免被SQL注入。SQL防火墙便是数据库层面的防火墙功能。该插件可以用来学习一些定义好的SQL规则,并将这些规则储存在数据库中作为白名单。当用户学习完成后,可以限制用户执行这些定义规则之外的风险操作。

使用说明

认识学习模式,预警模式与防火墙模式

image.png SQL防火墙共有三种模式,学习模式、预警模式与防火墙模式。 • 学习模式,防火墙会记录用户的SQL查询,作为用户常用查询的预期白名单,此时防火墙打开不做校验。 • 预警模式,此模式下,防火墙会对用户的SQL进行判断,如果用户的SQL不在白名单中,仍然会执行该SQL,但是会给用户一个报警,告知用户这条SQL不符合白名单记录的业务规则。 • 防火墙模式,此模式下,防火墙会对用户的SQL进行判断。如果用户的SQL不在白名单中,防火墙会拒绝该SQL的执行并告知用户这是一个错误。

SQL防火墙的使用

基于以上认识,防火墙的使用一般分为以下三个步骤。 • 1 打开防火墙的学习模式,这个过程中防火墙会记录用户的SQL,并加入白名单。这个过程建议持续一段较长的时间,使得用户所有的可能SQL尽可能的在数据库中执行过。 • 2 切换防火墙为预警模式,这个过程防火墙会对用户的一些不符合规则的SQL进行告警,用户结合自己的业务判断是否为风险SQL,如果这些SQL确实是用户需要的业务语句,则记录这些SQL,之后统一打开学习模式进行二次学习。 • 3 经过前两步,用户常用SQL已经被记录完毕,打开防火墙模式。此时不符合规则的SQL均不能被执行。

内核设计

简介

• PostgreSQL内置了很多的HOOK,这些HOOK可以方便开发者加入一些功能,例如在SQL parser阶段的HOOK,可以加入一些SQL统计,SQL篡改,SQL REWRITE的功能。在SQL执行阶段的HOOK,可以用来拒绝执行等。共享内存分配阶段的HOOK,可以用来分配用户自定义进程的共享内存等。 • SQL_FIREWALL是PostgreSQL的一个SQL防火墙插件,利用了一些HOOK,实现了SQL防火墙的功能。

image.png SQL防火墙大致可以分为三个模块,HOOK注入、用户接口与存储模块。 • HOOK 注入 采用pg_stat_statements的HOOK方式,对DDL与DML等SQL语句进行解析正则化。 • 用户接口 提供给用户若干操作函数,包括 统计SQL、导入导出白名单、重置白名单等功能 • 存储模块 提供一个运行时内存hash表与系统停止时文件的对等映射 下面分模块详细介绍

HOOK 注入设计

image.png SQL_FIREWALL一共改写了7个hook函数,关系如上图所示,其方式几乎等同于pg_stat_statments。 • pgss_shmem_startup与pgss_shmem_shutdown 分别负责在其启动时将文件中的内容加载到共享内存汇总与关闭时将共享内存中的内容存储回文件。 • pgss_ProcessUtility与 pgss_post_parse_analyze 分别负责DDL与DML的解析与记录,被记录到hash表中。 • pgss_ExecutorStart/pgss_ExecutorRun/pgss_ExecutorFinish/pgss_ExecutorStart 记录SQL的统计信息

用户接口设计

image.png SQL_FIREWALL提供了7个用户行数接口,供用户进行操作。 • sql_firewall_reset() 重置 所有的防火墙规则 • sql_firewall_statements() 展示所有的防火墙规则 • sql_firewall_stat_error_count() 查看强制模式下的错误数量 • sql_firewall_stat_warning_count() 查看宽容模式下的警告数量 • sql_firewall_stat_reset() 重置 错误与警告数量 • sql_firewall_export_rule() 导出 防火墙规则 • sql_firewall_import_rule() 导入 防火墙规则

存储模块设计

image.png SQL_FIREWALL 的数据和规则交替存储与共享内存与文件系统中。当系统运行时,SQL_FIREWALL读取本地文件到内存中,并生成一个临时文件;而当系统关闭时,SQL_FIREWALL将内存中的信息存储到文件中。