iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 29
2
Modern Web

ASP.NET MVC網頁程式介紹系列 第 29

[Day 29] 用ASP.NET MVC 做簡單的註冊及登入系統(五) - SQL Injection

今天要介紹SQL Injection,中文可以翻譯為SQL注入,網路上介紹的相關文章非常多,我這一次參考的是這一篇文章
SQL Injection 的多種攻擊方式與防護討論

SQL Injection簡單說就是利用程式的漏洞,原本應該是要輸入正確的帳號密碼才可以登入,但是以我昨天的語法,裡面有個很大的漏洞,語法如下

string strSQL = "SELECT 1 FROM `userdata` WHERE `account` = '" + account + "' AND `password` = '" + password + "';";

這次看到的文章的語法跟之前寫的不大一樣,如下圖
https://ithelp.ithome.com.tw/upload/images/20180107/20105694hJkx5bPf2O.jpg

帳號輸入 ' or 1=1; /* ,密碼輸入 */-- ,組起來的語法如下

SELECT * FROM `userdata` WHERE `account` = '' or 1=1; /* and `password` = '*/--';

實際嘗試的結果,在HeidiSQL可以顯示出資料,但是在我的程式裡面會丟出意外,最後還是無法成功登入

但是如果改成以下這樣
https://ithelp.ithome.com.tw/upload/images/20180107/20105694MHvwcjuqHi.jpg

重點是帳號,密碼的部分隨便輸入皆可

結果語法就會變成這樣

SELECT 1 FROM `userdata` WHERE `account` = '' OR 1=1 OR '' AND `password` = '(輸入的內容)';

這個句子有幾個部分

  • account = '' 這個條件一定不會成立
  • 1=1 這個條件一定會成立
  • '' AND password = '(輸入的內容)' 這個條件一定不會成立

三個條件用OR結合起來,結論是一定會成立,所以就可以成功登入,一般在登入之後會帶入使用者資料,會抓到第一個或最後一個使用者的資料(看程式怎麼寫),當然也可以判斷是不是抓到很多行,如果有很多行就不讓它通過,但這不是好方法。
其中一種方法是使用參數查詢的方式,我們改用參數代替實際的資料,然後再定義參數的內容,並且決定參數的型態,(如字串、數字等)在這個例子將整個輸入的內容當成字串,不論對方輸入什麼,都當成是獨立的字串來看,如此就不會有上述的問題,必須這個字串跟帳號、密碼內的字串一模一樣,才能夠順利通過,將上述的語法改成如下

string strSQL = "SELECT 1 FROM `userdata` WHERE `account` = @account AND `password` @password;";
MySqlCommand cmd = new MySqlCommand(strSQL, conn);
cmd.Parameters.Add("@account", MySqlDbType.VarChar).Value = account;
cmd.Parameters.Add("@password", MySqlDbType.VarChar).Value = password;

完整的函式如下

public bool CheckUserData(string account, string password)
{
    try
    {
        Connect();
        string strSQL = "SELECT 1 FROM `userdata` WHERE `account` = @account AND `password` = @password;";
        MySqlCommand cmd = new MySqlCommand(strSQL, conn);
        cmd.Parameters.Add("@account", MySqlDbType.VarChar).Value = account;
        cmd.Parameters.Add("@password", MySqlDbType.VarChar).Value = password;

        using (MySqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader.Read())
                return true;
        }
        return false;
    }
    catch(Exception ex)
    {
        string error = ex.ToString();
        return false;
    }
    finally
    {
        Disconnect();
    }
}

再輸入同樣的內容,就會得到以下的結果
https://ithelp.ithome.com.tw/upload/images/20180107/20105694WKi0ziNqUw.jpg
如此就不會讓對方順利蒙混過關了

--
小弟不才,
如果有謬誤或是要補充的,
都歡迎一起來討論!


上一篇
[Day 28] 用ASP.NET MVC 做簡單的註冊及登入系統(四)
下一篇
[Day 30] 用ASP.NET MVC 做簡單的註冊及登入系統(五) - 登入驗證
系列文
ASP.NET MVC網頁程式介紹30

尚未有邦友留言

立即登入留言