一什麼是SQL注入式攻擊
所謂SQL注入式攻擊
就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串
欺騙服務器執行惡意的SQL命令
在某些表單中
用戶輸入的內容直接用來構造(或者影響)動態SQL命令
或作為存儲過程的輸入參數
這類表單特別容易受到SQL注入式攻擊
常見的SQL注入式攻擊過程類如
⑴ 某個ASP
NET Web應用有一個登錄頁面
這個登錄頁面控制著用戶是否有權訪問應用
它要求用戶輸入一個名稱和密碼
⑵ 登錄頁面中輸入的內容將直接用來構造動態的SQL命令
或者直接用作存儲過程的參數
下面是ASP
NET應用構造查詢的一個例子
System
Text
StringBuilder
query = new System
Text
StringBuilder(
SELECT * from Users WHERE login =
)
Append(txtLogin
Text)
Append(
AND password=
)
Append(txtPassword
Text)
Append(
)
⑶ 攻擊者在用戶名字和密碼輸入框中輸入
或
=
之類的內容
⑷ 用戶輸入的內容提交給服務器之後
服務器運行上面的ASP
NET代碼構造出查詢用戶的SQL命令
但由於攻擊者輸入的內容非常特殊
所以最後得到的SQL命令變成
SELECT * from Users WHERE
login =
or
=
AND
password =
or
=
⑸ 服務器執行查詢或存儲過程
將用戶輸入的身份信息和服務器中保存的身份信息進行對比
⑹ 由於SQL命令實際上已被注入式攻擊修改
已經不能真正驗證用戶身份
所以系統會錯誤地授權給攻擊者
如果攻擊者知道應用會將表單中輸入的內容直接用於驗證身份的查詢
他就會嘗試輸入某些特殊的SQL字符串篡改查詢改變其原來的功能
欺騙系統授予訪問權限
系統環境不同
攻擊者可能造成的損害也不同
這主要由應用訪問數據庫的安全權限決定
如果用戶的帳戶具有管理員或其他比較高級的權限
攻擊者就可能對數據庫的表執行各種他想要做的操作
包括添加
刪除或更新數據
甚至可能直接刪除表
二如何防范
好在要防止ASP
NET應用被SQL注入式攻擊闖入並不是一件特別困難的事情
只要在利用表單輸入的內容構造SQL命令之前
把所有輸入內容過濾一番就可以了
過濾輸入內容可以按多種方式進行
⑴ 對於動態構造SQL查詢的場合
可以使用下面的技術
第一
替換單引號
即把所有單獨出現的單引號改成兩個單引號
防止攻擊者修改SQL命令的含義
再來看前面的例子
SELECT * from Users WHERE login =
or
=
AND password =
or
=
顯然會得到與
SELECT * from Users WHERE login =
or
=
AND password =
or
=
不同的結果
第二
刪除用戶輸入內容中的所有連字符
防止攻擊者構造出類如
SELECT * from Users WHERE login =
mas
AND password =
之類的查詢
因為這類查詢的後半部分已經被注釋掉
不再有效
攻擊者只要知道一個合法的用戶登錄名稱
根本不需要知道用戶的密碼就可以順利獲得訪問權限
第三
對於用來執行查詢的數據庫帳戶
限制其權限
用不同的用戶帳戶執行查詢
插入
更新
刪除操作
由於隔離了不同帳戶可執行的操作
因而也就防止了原本用於執行SELECT命令的地方卻被用於執行INSERT
UPDATE或DELETE命令
⑵ 用存儲過程來執行所有的查詢
SQL參數的傳遞方式將防止攻擊者利用單引號和連字符實施攻擊
此外
它還使得數據庫權限可以限制到只允許特定的存儲過程執行
所有的用戶輸入必須遵從被調用的存儲過程的安全上下文
這樣就很難再發生注入式攻擊了
⑶ 限制表單或查詢字符串輸入的長度
如果用戶的登錄名字最多只有
個字符
那麼不要認可表單中輸入的
個以上的字符
這將大大增加攻擊者在SQL命令中插入有害代碼的難度
⑷ 檢查用戶輸入的合法性
確信輸入的內容只包含合法的數據
數據檢查應當在客戶端和服務器端都執行
之所以要執行服務器端驗證
是為了彌補客戶端驗證機制脆弱的安全性
在客戶端
攻擊者完全有可能獲得網頁的源代碼
修改驗證合法性的腳本(或者直接刪除腳本)
然後將非法內容通過修改後的表單提交給服務器
因此
要保證驗證操作確實已經執行
唯一的辦法就是在服務器端也執行驗證
你可以使用許多內建的驗證對象
例如RegularExpressionValidator
它們能夠自動生成驗證用的客戶端腳本
當然你也可以插入服務器端的方法調用
如果找不到現成的驗證對象
你可以通過CustomValidator自己創建一個
⑸ 將用戶登錄名稱
密碼等數據加密保存
加密用戶輸入的數據
然後再將它與數據庫中保存的數據比較
這相當於對用戶輸入的數據進行了
消毒
處理
用戶輸入的數據不再對數據庫有任何特殊的意義
從而也就防止了攻擊者注入SQL命令
System
Web
Security
FormsAuthentication類有一個HashPasswordForStoringInConfigFile
非常適合於對輸入數據進行消毒處理
⑹ 檢查提取數據的查詢所返回的記錄數量
如果程序只要求返回一個記錄
但實際返回的記錄卻超過一行
那就當作出錯處理
以上資料參考與 賽迪網資料
但是我覺得在我們的ASP
NET程序裡防止SQL 注入
首先應該盡量使用存儲過程
關於使用存儲過程的好處在這裡就不展開討論了
使用參數傳遞變量
最不妥當的方法就是認為判斷SQL注入信息
盡管如此
可能日常開發中由於種種原因不能做的面面具道
存在各種各種的實際問題
現在是最近在一個項目中沒有考慮SQL注入項目補救寫的一個組件庫
資料也參考來源與網絡
實現很簡單
下面是具體實現的源程序
using System;
using System
Text
RegularExpressions;
using System
Web;
namespace FSqlKeyWord
…{
/**//// <summary>
/// SqlKey 的摘要說明
/// </summary>
public class SqlKey
…{
private HttpRequest request;
private const string StrKeyWord = @
select|insert|delete|from|count(|drop table|update|truncate|asc(|mid(|char(|xp_cmdshell|exec master|netlocalgroup administrators|:|net user|
|or|and
;
private const string StrRegex = @
[
|;|
|/|(|)|[|]|}|{|%|@|*|!|
]
;
public SqlKey(System
Web
HttpRequest _request)
…{
//
// TODO: 在此處添加構造函數邏輯
//
this
request = _request;
}
/**//// <summary>
/// 只讀屬性 SQL關鍵字
/// </summary>
public static string KeyWord
…{
get
…{
return StrKeyWord;
}
}
/**//// <summary>
/// 只讀屬性過濾特殊字符
/// </summary>
public static string RegexString
…{
get
…{
return StrRegex;
}
}
/**//// <summary>
/// 檢查URL參數中是否帶有SQL注入可能關鍵字
/// </summary>
/// <param name=
_request
>當前HttpRequest對象</param>
/// <returns>存在SQL注入關鍵字true存在
false不存在</returns>
public bool CheckRequestQuery()
…{
if (request
QueryString
Count !=
)
…{
//若URL中參數存在
逐個比較參數
for (int i =
; i < request
QueryString
Count; i++)
…{
// 檢查參數值是否合法
if (CheckKeyWord(request
QueryString[i]
ToString()))
…{
return true;
}
}
}
return false;
}
/**//// <summary>
/// 檢查提交表單中是否存在SQL注入可能關鍵字
/// </summary>
/// <param name=
_request
>當前HttpRequest對象</param>
/// <returns>存在SQL注入關鍵字true存在
false不存在</returns>
public bool CheckRequestForm()
…{
if (request
Form
Count >
)
…{
//獲取提交的表單項不為
逐個比較參數
for (int i =
; i < request
Form
Count; i++)
…{
//檢查參數值是否合法
if (CheckKeyWord(request
Form[i]))
…{
//存在SQL關鍵字
return true;
}
}
}
return false;
}
/**//// <summary>
/// 靜態方法
檢查_sword是否包涵SQL關鍵字
/// </summary>
/// <param name=
_sWord
>被檢查的字符串</param>
/// <returns>存在SQL關鍵字返回true
不存在返回false</returns>
public static bool CheckKeyWord(string _sWord)
…{
if (Regex
IsMatch(_sWord
StrKeyWord
RegexOptions
IgnoreCase) || Regex
IsMatch(_sWord
StrRegex))
return true;
return false;
}
/**//// <summary>
/// 反SQL注入
返回
無注入信息
否則返回錯誤處理
/// </summary>
/// <returns>返回
無注入信息
否則返回錯誤處理</returns>
public string CheckMessage()
…{
string msg =
;
if (CheckRequestQuery()) //CheckRequestQuery() || CheckRequestForm()
…{
msg =
<span style=
font
size:
px;
>非法操作!<br>
;
msg +=
操作IP:
+ request
ServerVariables[
REMOTE_ADDR
] +
<br>
;
msg +=
操作時間
+ DateTime
Now +
<br>
;
msg +=
頁面
+ request
ServerVariables[
URL
]
ToLower() +
<br>
;
msg +=
<a #
onclick=
history
back()
>返回上一頁</a></span>
;
}
return msg
ToString()
}
}
}
From:http://tw.wingwit.com/Article/program/net/201311/11680.html