public class SqlInject:Page { //检测到注入后的处理方式: 0:仅警告;1:警告+记录;2:警告+自定义错误页面;3:警告+记录+自定义错误页面 private const int _type = 0; private const string errRedirectPage = "/err.aspx"; //如果记录注入信息,那么请设置:errMDBpath:数据库路径 private const string errMDBpath = "/SqlInject.mdb"; //过滤特征字符 //过滤特征字符 private static string StrKeyWord = ConfigurationManager.AppSettings["SqlKeyWord"]; //@"select|insert|delete|from|count(|drop table|update|truncate|asc(|mid(|char(|xp_cmdshell|exec|master|net local group administrators|net user|or|and"; private static string StrRegex = ConfigurationManager.AppSettings["SqlRegex"]; //@";|/|(|)|[|]|{|}|%|@|*|‘|!"; // 原始过滤条件:【-|;|,|/|(|)|[|]|{|}|%|@|*|‘|!】 private HttpRequest request; public SqlInject(System.Web.HttpRequest _request) { this.request = _request; } ///<summary> ///检测SQL注入及记录、显示出错信息 ///</summary> public void CheckSqlInject() { bool isInject = false; if (CheckRequestQuery() || CheckRequestForm()) { isInject = true; } else { return; } switch (_type) { case 0: ShowErr(); break; case 1: ShowErr(); SaveToMdb(); break; case 2: ShowErr(); string temp; System.Web.HttpContext.Current.Response.Write("<script>setTimeout(\"" + "location.href=‘" + errRedirectPage + "‘" + "\",5000)</script>"); break; case 3: ShowErr(); SaveToMdb(); System.Web.HttpContext.Current.Response.Write("<script>setTimeout(\"" + "location.href=‘" + errRedirectPage + "‘" + "\",5000)</script>"); break; default: break; } System.Web.HttpContext.Current.Response.End(); } private void SaveToMdb() { OleDbConnection conn = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + Server.MapPath(errMDBpath)); conn.Open(); OleDbCommand cmd = conn.CreateCommand(); cmd.CommandText = "insert into [Record] (sIP,sDate,sPath) values (‘" + request.ServerVariables["REMOTE_ADDR"].ToString() + "‘,‘" + DateTime.Now + "‘,‘" + request.ServerVariables["URL"].ToLower() + RelaceSingleQuotes(request.QueryString.ToString()) + "‘)"; int code = cmd.ExecuteNonQuery(); if (code == 1) HttpContext.Current.Response.Write("<br>****以上信息已记录至日志数据库****"); else HttpContext.Current.Response.Write("<br>日志数据库出错"); conn.Close(); } private string RelaceSingleQuotes(string _url) { string URL = _url.Replace("‘", "单引号"); return URL; } private void ShowErr() { //string msg = @"<font color=red>请不要尝试未授权之入侵检测!</font>" + @"<br><br>"; //msg += @"操作IP:" + request.ServerVariables["REMOTE_ADDR"] + @"<br>"; //msg += @"操作时间:" + DateTime.Now + @"<br>"; //msg += @"页面:" + request.ServerVariables["URL"].ToLower() + request.QueryString.ToString() + @"<br>"; //msg += @"<a href=‘#‘ onclick=‘javascript:window.close()‘>关闭</a>"; //System.Web.HttpContext.Current.Response.Clear(); //System.Web.HttpContext.Current.Response.Write(msg); HttpContext.Current.Response.Write("<script>alert(‘请不要尝试未授权之入侵检测!‘);javascript:history.go(-1);</script>"); } ///<summary> /// 特征字符 ///</summary> public static string KeyWord { get { return StrKeyWord; } } ///<summary> /// 特征符号 ///</summary> public static string RegexString { get { return StrRegex; } } ///<summary> ///检查字符串中是否包含Sql注入关键字 /// <param name="_key">被检查的字符串</param> /// <returns>如果包含注入true;否则返回false</returns> ///</summary> private static bool CheckKeyWord(string _key) { string[] pattenString = StrKeyWord.Split(‘|‘); string[] pattenRegex = StrRegex.Split(‘|‘); foreach (string sqlParam in pattenString) { if (_key.Contains(sqlParam + " ") || _key.Contains(" " + sqlParam)) { return true; } } foreach (string sqlParam in pattenRegex) { if (_key.Contains(sqlParam)) { return true; } } return false; } ///<summary> ///检查URL中是否包含Sql注入 /// <param name="_request">当前HttpRequest对象</param> /// <returns>如果包含注入true;否则返回false</returns> ///</summary> public bool CheckRequestQuery() { if (request.QueryString.Count > 0) { foreach (string sqlParam in this.request.QueryString) { if (sqlParam == "__VIEWSTATE") continue; if (sqlParam == "__EVENTVALIDATION") continue; if (CheckKeyWord(request.QueryString[sqlParam].ToLower())) { return true; } } } return false; } ///<summary> ///检查提交的表单中是否包含Sql注入 /// <param name="_request">当前HttpRequest对象</param> /// <returns>如果包含注入true;否则返回false</returns> ///</summary> public bool CheckRequestForm() { if (request.Form.Count > 0) { foreach (string sqlParam in this.request.Form) { if (sqlParam == "__VIEWSTATE") continue; if (sqlParam == "__EVENTVALIDATION") continue; if (CheckKeyWord(request.Form[sqlParam])) { return true; } } } return false; } } }
在web编程中都有被sql注入的风险,要防止sql注入,最基本就是从编写代码的时候开始防护
在web.config中加入
<appSettings> <add key="SqlKeyWord" value="select|insert|delete|from|count(|drop table|update|truncate|asc(|mid(|char(|xp_cmdshell|exec|master|net local group administrators|net user|or|and"/> <add key="SqlRegex" value=";|(|)|[|]|{|}|%|@|*|‘|!"/> </appSettings>
然后在Global文件中加入
void Application_BeginRequest(object sender, EventArgs e) { //防SQL注入代码 SqlInject myCheck = new SqlInject(this.Request); myCheck.CheckSqlInject(); }
对于软件方面的防护,微软官方给了一个UrlScan的工具
安装完软件后要重启一下iis才能生效
转载自 http://netsecurity.51cto.com/art/201301/375797_1.htm