摘要: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