ASP.NET Login元件使用已存在的資料庫 及 SQL Injection

摘要:ASP.NET Login元件使用已存在的資料庫 及 SQL Injection

 


看到 Topcat 寫的「ASP.NET 2.0如何使用Login來存取自己的使用者資料庫」,就想到前一陣子用的一個方法沒上來記錄一下,所以用點時間跟大家分享一下。

通常在寫系統時,防護力最弱的地方就在 login 頁,因為大家都能 Access 得到,雖然 Login 頁不會有啥重要的資料,但是如果開發系統,其使用的 DB User Account 都是同一個話,其實那就代表著能在 Login 頁撈到所有具有權限讀取的資料。

第一步:當然是將 Login 頁所使用的 DB Account 切開,就只單純的唯讀存取使用者帳號相關資訊。

一般來說工號、帳號、員工編號,都具有某種格式的規格(樣板),所以在驗證輸入是否合理判斷上比較容易;但是密碼欄就比較難規範使用者怎麼設定,相對的危險性就會升高,那如果分辨不出來合理與否,就丟到 SQL 裡去執行是相當危險的。

早期撈資料的方式

SELECT user_id,department FROM users WHERE username='帳號輸入' AND password='密碼輸入'

這種直接串使用者輸入資料部分,很容易發生 SQL Injection 問題,例如

帳號輸入 = 'or 1=1 ; drop table users --

整個來看,就變成了

SELECT user_id,department FROM users WHERE username=''or 1=1 ; drop table users -- ' AND password='密碼輸入'

怎麼「SELECT user_id,department FROM users WHERE username=''or 1=1」執行都是正確的,而同一  Transaction 被多加了「 drop table users」,兩個 T-SQL 都會被執行,而後面接的密碼部分備註解掉了,後果當然很可怕。

------上面一小段是在說 SQL Injection 的問題 -----

為了避免被執行「or 1=1」這樣的東西,對使用者輸入的內容做檢查就很重要。剛剛說過對工號檢查容易,但密碼欄是較難規範輸入值與長度

該怎麼避免在密碼欄被輸入有害的執行內容,造成資料庫的傷害?

我想到的答案,就是不要將使用者輸入的密碼丟到 SQL 去執行,等利用工號撈出來後再比對。為了安全的理由我們必須對密碼內容做加密~

加密的方法百百款,我要叫介紹的是最簡單的 MD5 方式,MD5 在 VS.NET 與 MS_SQL 都是支援的。

當然要自行開發加密方式也是ok的啦~

整個流程可以參考最上方的圖片。

------------------------------

在 SQL 端對重要對欄位使用 MD5 的加密方法「 SQL 資料庫加密SQL + ASP.NET 欄位加密 varbinary 處理

sys.fn_VarBinToHexStr(HASHBYTES('MD5', dbo.account.password)) AS password   '要加 Alias 唷,不然前端可能會抓不到

在 VS.NET 對內容做MD5 的方法

DIM str AS STRING = "0x" & LCase(FormsAuthentication.HashPasswordForStoringInConfigFile(Login1.Password, "MD5"))

-----------------------------

至於怎麼使用 Login 元件時呼叫自己的資料庫,各位可以參考 Topcat大 所說明的方法,至於我只是在  Protected Sub Login1_Authenticate 的執行中,去撈取我的資料庫,然後加密後做比對,如果比對成功就宣告「 e.Authenticated = True」其 e 為 System.Web.UI.WebControls.AuthenticateEventArgs。

那比對失敗呢?

那就 e.Authenticated = False 並且重新載入 login.aspx 囉,至於要不要清掉 Login1.UserName 就看各位囉!

~ End