標籤:驗證 使用者輸入 script 沒有 images 檢查 mon 才有 bsp
在開發程式的過程中,稍微不注意就會隱含有sql注入的危險。今天我就來說下,ASP.NET mvc 5使用Filter過濾Action參數防止sql注入,讓你代碼安全簡潔。不用每下地方對參數的值都進行檢查,看是使用者輸入的內容是否有危險的sql。如果每個地方都要加有幾個缺點:
1、工作量大
2、容易遺漏
3、不容易維護
下面我通過寫一個過濾防止sql的屬性類別,對Action執行前對Action的參數進行處理,如果有其值有sql語句,就會這些非法字元替換為空白字串。
一、sql注入的例子:
上面的輸入有兩個輸入框,使用者可以輸入任何的值,包括有sql注入的值。
後台代碼:
AdminController.cs
public class AdminController : Controller { public ActionResult Index(string name = "", string loginName = "", int page = 1) { ViewBag.Name = name; ViewBag.LoginName = loginName; var r = DAdmin.GetList(name, loginName, page, 2); return View(r); } }}
DAdmin.cs:
public class DAdmin{ public static PageDataView<MSys_Admin> GetList(string name, string loginName, int page,int pageSize=10) { PageCriteria criteria = new PageCriteria(); criteria.Condition = "1=1"; if (!string.IsNullOrEmpty(name)) criteria.Condition += string.Format(" and Name like ‘%{0}%‘", name); if (!string.IsNullOrEmpty(loginName)) criteria.Condition += string.Format(" and LoginName like ‘%{0}%‘", loginName); criteria.CurrentPage = page; criteria.Fields = "*"; criteria.PageSize = pageSize; criteria.TableName = "Sys_Admin a"; criteria.PrimaryKey = "UID"; var r = Common.GetPageData<MSys_Admin>(criteria); return r; }}
上面對使用者輸入的name和loginName兩個參數沒有判斷是否有sql注入的非法字元,就直接拼接到sql語句,到資料庫中執行,這樣是非常危險的。
1、比如使用者在name輸入這樣的內容:
%‘--%
這樣拼接出來的sql語句就成了
SELECT * FROM Sys_Admin WHERE Name like ‘%‘--%‘
這樣“--”是sql的注釋標記後面再拼接的sql語句都當成注釋了,這樣有效就成了這樣的sql語句:
SELECT * FROM Sys_Admin WHERE Name like ‘%‘
這表示顯示全部的記錄。如果是登入的sql就會跳過使用者名稱、密碼的驗證。
2、如果使用者name輸入內容帶有insert或delete或者drop,比如:
namer人值為:%‘;DELETE FROM Sys_Admin--%
拼接成的sql成了:
SELECT * FROM Sys_Admin WHERE Name like ‘%‘;DELETE FROM Sys_Admin--%‘
這樣一執行就把Sys_Admin表的記錄全部刪除了。
總結:上面可以看到這種sql注入是多麼的危險。
二、解決MVC sql注入方案1、定義一個防止sql注入的字串輔助類
{ public static string FilterSql(string s) { if (string.IsNullOrEmpty(s)) return string.Empty; s = s.Trim().ToLower(); s = ClearScript(s); s = s.Replace("=", ""); s = s.Replace("‘", ""); s = s.Replace(";", ""); s = s.Replace(" or ", ""); s = s.Replace("select", ""); s = s.Replace("update", ""); s = s.Replace("insert", ""); s = s.Replace("delete", ""); s = s.Replace("declare", ""); s = s.Replace("exec", ""); s = s.Replace("drop", ""); s = s.Replace("create", ""); s = s.Replace("%", ""); s = s.Replace("--", ""); return s; }}
這個類對上面sql相關的字串都替換掉。
2、定義一個用來檢查並處理Action參數的屬性類別
public class AntiSqlInjectAttribute:FilterAttribute,IActionFilter{ public void OnActionExecuted(ActionExecutedContext filterContext) { } public void OnActionExecuting(ActionExecutingContext filterContext) { var actionParameters = filterContext.ActionDescriptor.GetParameters(); foreach (var p in actionParameters) { if (p.ParameterType == typeof(string)) { if (filterContext.ActionParameters[p.ParameterName] != null) { filterContext.ActionParameters[p.ParameterName] = StringHelper.FilterSql(filterContext.ActionParameters[p.ParameterName].ToString()); } } } }}
說明:這個屬性類別是繼承了類FilterAttribute和實現了介面IActionFilter,這裡在方法OnActionExecuting處理Action的參數,OnActionExecuting是在Action執行之前啟動並執行方法,而OnActionExecuted是在Action執行之後啟動並執行方法。
p.ParameterType == typeof(string)
因為sql注入只有參數類型為字串的時候才有可能所以這裡只對Action參數為字串的參數進行處理。
filterContext.ActionParameters[p.ParameterName] =
StringHelper.FilterSql(filterContext.ActionParameters[p.ParameterName].ToString());
是用過濾之後的安全的Action參數值替換原來的原始值。
3、防止sql注入屬性類別的在MVC的Controller中的使用
public class AdminController : Controller{ [AntiSqlInject] public ActionResult Index(string name = "", string loginName = "", int page = 1) { ViewBag.Name = name; ViewBag.LoginName = loginName; var r = DAdmin.GetList(name, loginName, page, 2); return View(r); }}
需要對Action的參數進行sql檢查,只用在前面加上,上面定義的屬性類別AntiSqlInject。這個屬性類別可以用在任何的需要防止sql注入的Action上,根本不用對手動的去過濾程式中擷取到的所有參數,安全、方便簡潔。
ASP.NET MVC 5使用Filter過濾Action參數防止sql注入,讓你代碼安全簡潔