OneProxy :: 如何防止SQL注入式攻击,有效保障数据库中信息的安全?

仅依靠访问控制和前后端密码分离还不足以保证数据库的安全,在应用层还有其他的安全风险,比如API被劫持调用、或者直接被黑客使用SQL注入攻击(见Wikipedia定义、及SQL注入例子)拖取大量的数据,俗称拖库攻击。在网上也可以找到专门的工具(如sqlmap)来自动地检测和定位可被SQL注入的安全漏洞,几乎每个星期都可以看到某某网站有信息泄露漏洞,其中SQL注入方式漏洞的危害最大,可以在极短的时间内取走大量的信息,需要加以特别的关注和防范。

oneproxy_sql_injection

如何有效地防止SQL注入式攻击是安全的关键,要怎么样做呢?是否可以通过设置几条精良的规则来检测和防范? 在和众多安全专家技术交流的过程中,大家一致认为很难建立一套严格的规则来防范。在网络交换机、路由器、防火墙上可以有一些很好的规则来做入侵检测,但却找不到很好的规则来识别哪些SQL是合理的应用请求,哪些可能是非法的注入过的SQL语句。误杀SQL语句会对业务造成影响,误入SQL又会有严重的安全问题,并且黑客的攻击技术越来越高明,实在难以应付。

对于OneProxy中间件来讲,所有流量经过它并且又懂数据库的协议,可以在一个安全的环境里收集到所有业务中会用到的SQL语句,并且在收集完后可以进行进一步的人工检查,就意味着不在这个列表上的SQL都可以认为是非法的,应当予以拦截的。OneProxy可以根据一个已知的SQL的名单(SQL白名单)来自动检测或拦截其他所有未知的SQL语句,称这个功能为SQL白名单功能,只要在安全的环境里,采集足够长的时间(比如花上几周或几个月),就可以得到非常完整的SQL白名单列表, 通过OneProxy管理端口的“list sqltext”命令就可以列出所有执行过的SQL语句,并可以将这些SQL语句保存下来。

mysql> list sqltext;
+------------+------------------------------------+
| HASHCODE   | SQLTEXT                            |
+------------+------------------------------------+
| 4272914078 | select * from my_hash where id = ? |
| 1561995348 | show tables                        |
| 1280354203 | select * from my_list where id = ? |
+------------+------------------------------------+
3 rows in set (0.00 sec)
mysql> save sql '/tmp/firweall.sql';
Query OK, 0 rows affected (0.00 sec)

在使用“save sql”命令保存所有的SQL后,可以在OneProxy里进行SQL装载,将保存的SQL语句视作SQL白名单,然后再打开SQL防火墙选项来开启SQL白名单接截功能。

mysql> load sql '/tmp/firweall.sql';
Query OK, 0 rows affected (0.00 sec)

mysql> set sql_firewall on;
Query OK, 0 rows affected (0.00 sec)

开启后登录OneProxy工作端口,随意执行一些SQL,就会发现以前没有执行过的SQL(不在SQL白名单中)是不能被执行的,而已经执行过的SQL则可以继续执行。

mysql> select * from my_list;
ERROR 1045 (28000): Statement was blocked by OneProxy SQL Firewall
mysql> select * from my_list where id = 9;
+----+------+-------+
| id | col2 | col3  |
+----+------+-------+
|  9 |  102 | Row 9 |
+----+------+-------+
1 row in set (0.02 sec)

mysql> select * from my_hash;
ERROR 1045 (28000): Statement was blocked by OneProxy SQL Firewall
mysql> select * from my_hash where id = 9;
+----+------+-------+
| id | col2 | col3  |
+----+------+-------+
|  9 |  102 | Row 9 |
+----+------+-------+
1 row in set (0.00 sec)

在SQL白名单中,所有的字符串和数字都会被替换成问号(“?”)来进行特征归类,使用不同的值是可以被执行的,但如果想更改一下SQL语句(SQL注入),则是不可能的,从而彻底杜绝了SQL注入的可能。

mysql> select * from my_hash where id = 9 or 1=1; 
ERROR 1045 (28000): Statement was blocked by OneProxy SQL Firewall

可以在一个可信任的环境里收集SQL语句,经过仔细审核后再作为标准的SQL白名单。如果SQL白名单中有上万条SQL语句,会不会导致性能低下?答案是不会的,会用高效的Hash表的形式在内存中索引SQL白名单,从而保证白名单的查找时间和SQL的条目无关(这是由Hash算法决定的),SQL白名单机制可能是唯有真正有效的防止SQL注入攻击的方案。