我们需要一种工具。许多安全机构和人员提出了不少对付这种攻击的方法。今天我们看一个不错的工具GreenSQL,可以说它是一个MySQL数据库防火墙,可以过滤SQL注入攻击。
【51CTO.com 独家特稿】SQL注入攻击的危害早已为人所熟知,这种攻击准许攻击者在你的数据库上执行任意的SQL命令。要对付这种攻击,我们对于Web用户 所提供的任何数据,不管是通过HTTP方式,还是通过CGI参数方式提供的,都要经过验证,以确保其不包含非法信息。
这是解决问题的根本之道。我们需要一种工具。许多安全机构和人员提出了不少对付这种攻击的方法。今天我们看一个不错的工具GreenSQL,可以说它是一个MySQL数据库防火墙,可以过滤SQL注入攻击。
它位于网站和MySQL数据库之间,可以决定哪些SQL语句可以执行,哪些不应当执行。再加上其Web界面,使得 用户可以通过浏览器来管理GreenSQL。GreenSQL的设计目的就是用作MySQL数据库的一个代理服务器。它不是将用户的请求直接连接到MySQL数据库,而是连接到GreenSQL。 GreenSQL将合法的SQL提交给MySQL数据库并返回结果。
如果GreenSQL检测到一条不属于白名单并包含恶意SQL的语句,它将阻止此SQL 并返回一个空结果,不与MySQL数据库发生联系。笔者完成此文时,Fedora、openSUSE、 Ubuntu 等Linux发行版本并没有包含GreenSQL。
在本文中,笔者将在一台64位的Fedora 9计 算机上从源代码安装greensql-fw 0.8.4。安装过程并没有使用自动化的工具,所以必须手动设置一些东西,如配置文件、系统用户、MySQL配置、日志文件、/etc/init.d等。 这些过程在install.txt文件中有明确说明,所以并不太费力。当然,通过执行脚本字典中的几个脚本外壳,你也可以完成安装的不 少内容。为编译应用程序,可以简单地执行“make”,如下所示:
复制 $ tar xzf /.../greensql-fw-0.8.4.tar.gz
$ cd greensql-fw-0.8.4/
$ make
...
connection.hpp:29: error: field 'proxy_event' has incomplete type
connection.hpp:30: error: field 'client_event' has incomplete type
可以看出,在编译开始后,我们收到了几个错误,这是由于在Fedora 9上安装时,笔者并没有安装libevent-devel。在安装好libevent-devel后,又发现需要修改/usr/include/event.h,为编译事件代码,需要将sys/types.h包括进去。
复制 vi /usr/include/event.h ... #include #include #include #include
在使用“make -k”命令时,有几个文件又出现了差错,这些文件调用了字符串函数,如“strcasecmp”,这是由于没有包括 string.h头文件所致。对读者来说,根据所使用的gcc的版本的不同,在编译GreenSQL时,可能会出现类似或不类似于下面的一些问 题:
复制 $ cd src $ vi mysql/mysql_con.cpp ...
复制 // License: GPL v2 (http://www.gnu.org/licenses/gpl.html) //
复制 #include
#include "mysql_con.hpp" ...
复制 $ vi config.hpp ... #ifndef GREEN_SQL_CONFIG_HPP #define
GREEN_SQL_CONFIG_HPP #include ...
复制 $ vi ../src/parser/expression.hpp ... #ifndef _SQL_EXPRESSION_HPP_
#define _SQL_EXPRESSION_HPP_ #include ...
如果你在一个64位的发行版本上编译GreenSQL,可能还需要稍稍修改Makefile,这样编译生成程序才能检查lib64而不是lib目录,如 下所示:
复制 LIBS:=-L/usr/local/lib -L/usr/local/lib/mysql -L/usr/lib64/mysql -lmysqlclient -levent -lpcre
greensql-fw: $(OBJS) ... $ make
编译完成,下面显示的完成安装的命令:
复制 greensql-fw-0.8.4]# cd ./scripts/
复制 # ./setup_user.sh done...
复制 # ./greensql-create-db.sh -----------------------------
---------------- The following settings will be used: MySQL admin user: [root]
复制 MySQL admin password: [] MySQL server
address: [127.0.0.1] GreenSQL configuration DB name: [greendb]
复制 DB user to create: [green]
复制 Password to set: [pwd] Do
you want to change anything? [y/N] y
复制 MySQL admin user [root]: MySQL admin password []: XXxxXXxxXXxx-FIXME MySQL
server address (you can use ip:port string) [127.0.0.1]:
复制 GreenSQL config db name [greendb]: GreenSQL DB user name
[green]: greendb GreenSQL DB user password [pwd]: greendbpass
复制 --------------------------------------------- The
following settings will be used: Do you want to change anything? [y/N]
复制 Creating MySQL database...
复制 Creating MySQL tables...
复制 GreenSQL configuration file is not writable!!! Check that [database] section
contains the following settings in /etc/greensql/greensql.conf [database]
复制 dbhost=127.0.0.1 dbname=greendb
dbuser=greendb dbpass=greendbpass # dbport=3306 ...
复制 # ./setup_conf.sh done...
复制 # ./setup_log.sh done... #
./setup_binary.sh done...
复制 # vi /etc/greensql/greensql.conf ... [database] dbhost=127.0.0.1 dbname=greendb
dbuser=greendb dbpass=greendbpass ...
复制 # chkconfig --add greensql service greensql does not support chkconfig #
/etc/init.d/greensql start
软件包的install.txt文件描述了手动安装方法,与脚本所使用的命令相同。使用脚本可能更好一些,因为这样可以提高安装速度, 而安装程序基本相同。安装指南推荐在/etc/greensql目录之前设置MySQL数据库,不过如果你这样做的话,有可能无法找到配置文件 ,所以你必须手动更改/etc/greensql/greensql.conf文件。你对greensql.conf作出的唯一主要更改是获取MySQL数据库参数。为测试需要,笔者创建了一个称为“test”的数据库,并允许用户“ben”自由访问,命令如下:
复制 # mysql -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> GRANT ALL ON test.* TO ben@"%";
mysql> FLUSH PRIVILEGES;
默认情况下,GreenSQL运行在3305端口上,小于MySQL的默认端口(3306)。如果你使用mysql控制台客户端并连接到GreenSQL的3305 端口上,你将无法创建新表。如果你直接通过3306端口连接到MySQL,就可以创建新表。
复制 $ mysql --verbose -h 127.0.0.1 -P 3305 test
mysql> create table foo ( id int );
--------------
create table foo ( id int )
--------------
Query OK, 0 rows affected (0.01 sec)
mysql> insert into foo values ( 55 );
--------------
insert into foo values ( 55 )
--------------
ERROR 1146 (42S02): Table 'test.foo' doesn't exist
$ mysql --verbose -h 127.0.0.1 -P 3306 test
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> create table foo ( id int );
--------------
create table foo ( id int )
--------------
Query OK, 0 rows affected (0.01 sec)
mysql> insert into foo values ( 55 );
--------------
insert into foo values ( 55 )
--------------
Query OK, 1 row affected (0.00 sec)
mysql> insert into foo values ( 131 );
--------------
insert into foo values ( 131 )
--------------
Query OK, 1 row affected (0.00 sec)
mysql> select * from foo;
--------------
select * from foo
--------------
+------+
| id |
+------+
| 55 |
| 131 |
+------+
2 rows in set (0.00 sec)
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39.
如果使用默认配置,你将无法通过GreenSQL防火墙丢弃数据表。这倒无妨,因为表结构不太可能经常改变,更不可能通过Web界面改 变。
复制 $ mysql --verbose -h 127.0.0.1 -P 3305 test
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> select * from foo;
--------------
select * from foo
--------------
+------+
| id |
+------+
| 55 |
| 131 |
+------+
2 rows in set (0.00 sec)
mysql> drop table foo;
--------------
drop table foo
--------------
Query OK, 0 rows affected (0.00 sec)
mysql> select * from foo;
--------------
select * from foo
--------------
+------+
| id |
+------+
| 55 |
| 131 |
+------+
2 rows in set (0.01 sec)
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
注入测试看来没有如所期望的那样正常工作。第一次测试是在条件一直为真时删除表。这会清除表内的所有数据,留下一个空表。默 认地此查询会通过防火墙进行:
复制 $ mysql --verbose -h 127.0.0.1 -P 3305 test
mysql> delete from foo where 1=1;
--------------
delete from foo where 1=1
--------------
Query OK, 2 rows affected (0.00 sec)
mysql> select * from foo;
--------------
select * from foo
--------------
Empty set (0.00 sec)
对于上面的SQL删除命令来说,/var/log/greensql.log文件包含了下面的信息:
复制 SQL_DEBUG: QUERY command[]: delete from foo where 1=1
SQL_DEBUG: AFTER NORM : delete from foo where ?=?
SQL_DEBUG: RISK : 0
/etc/greensql/greensql.conf文件准许你设置某些内容的风险程度。例如,你可以将10指定给union关键字使用,或者在查询中使用 直接的变量比较(如同1=2之类的东西)。这些变量包括“block_level = 30”,所以RISK大于30的任何查询都不转发给MySQL服务器 。为了让GreenSQL标记出上面的查询,笔者将risk_var_cmp_var 和 risk_always_true从默认的30增加至150。但很不幸,这次查询 看起来仍是风险为零。
复制 SQL_DEBUG: QUERY command[]: delete from foo where id=181 or 1=1
SQL_DEBUG: AFTER NORM : delete from foo where id=? or ?=?
SQL_DEBUG: RISK : 0
SQL_DEBUG: QUERY command[]: delete from s where comment = 'whatever' or '1'='1'
SQL_DEBUG: AFTER NORM : delete from s where comment = ? or ?=?
SQL_DEBUG: RISK : 0
笔者做了许多尝试,结果都是一样的,即GreenSQL都将前面的不怀好意的查询的风险看成是零,笔者又试用了一下SELECT查询。这竟然 是使GreenSQL工作的一个关键,即可以阻止恶意查询,如日志文件的一个片断部分所示:
复制 SQL_DEBUG: QUERY command[]: select * from folks where name='sam' or '1'='1'
SQL_DEBUG: AFTER NORM : select * from folks where name=? or ?=?
DEBUG: Query has 'or' token
DEBUG: Variable comparison only
SQL_DEBUG: RISK : 35
由于select语句中的SQL注入允许用户在没有口令的情况可以登录进入一个站点,让GreenSQL检查一下你的select未尝不是一个好主 意。不过,笔者希望GreenSQL的未来版本可以将保护扩展到delete语句,因为它可以清除整个数据表。
【51CTO.COM 独家特稿,转载请注明出处及作者!】
【编辑推荐】
基于IE的MIME sniffing功能的跨站点脚本攻击
恶意软件反检测技术简介:模拟器超限技术
安全专家详谈:对付恶意软件的策略及方法