也谈C#.NET防止SQL注入式攻击

 #region 防止sql注入式攻击(可用于UI层控制)

        ///
        /// 判断字符串中是否有SQL攻击代码,by fangbo.yu 2008.07.18
        ///
        /// 传入用户提交数据
        /// true-安全;false-有注入攻击现有;
        public bool ProcessSqlStr(string inputString)
        {
            string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\*|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";
            try
            {
                if ((inputString != null) && (inputString != String.Empty))
                {
                    string str_Regex = @"\b(" + SqlStr + @")\b";

                    Regex Regex = new Regex(str_Regex, RegexOptions.IgnoreCase);
                    //string s = Regex.Match(inputString).Value;
                    if (true == Regex.IsMatch(inputString))
                        return false;

                }
            }
            catch
            {
                return false ;
            }
            return true;
        }


        ///
        /// 处理用户提交的请求,校验sql注入式攻击,在页面装置时候运行
        /// System.Configuration.ConfigurationSettings.AppSettings["ErrorPage"].ToString(); 为用户自定义错误页面提示地址,
        /// 在Web.Config文件时里面添加一个 ErrorPage 即可
        ///
        ///    
        ///
        public void ProcessRequest()
        {
            try
            {
                string getkeys = "";
                string sqlErrorPage = System.Configuration.ConfigurationSettings.AppSettings["ErrorPage"].ToString();
                if (System.Web.HttpContext.Current.Request.QueryString != null)
                {

                    for (int i = 0; i < System.Web.HttpContext.Current.Request.QueryString.Count; i++)
                    {
                        getkeys = System.Web.HttpContext.Current.Request.QueryString.Keys[i];
                        if (!ProcessSqlStr(System.Web.HttpContext.Current.Request.QueryString[getkeys]))
                        {
                            System.Web.HttpContext.Current.Response.Redirect(sqlErrorPage + "?errmsg=" + getkeys + "有SQL攻击嫌疑!");
                            System.Web.HttpContext.Current.Response.End();
                        }
                    }
                }
                if (System.Web.HttpContext.Current.Request.Form != null)
                {
                    for (int i = 0; i < System.Web.HttpContext.Current.Request.Form.Count; i++)
                    {
                        getkeys = System.Web.HttpContext.Current.Request.Form.Keys[i];
                        if (!ProcessSqlStr(System.Web.HttpContext.Current.Request.Form[getkeys]))
                        {
                            System.Web.HttpContext.Current.Response.Redirect(sqlErrorPage + "?errmsg=" + getkeys + "有SQL攻击嫌疑!");
                            System.Web.HttpContext.Current.Response.End();
                        }
                    }
                }
            }
            catch
            {
                // 错误处理: 处理用户提交信息!
            }
        }
        #endregion


       

        #region 转换sql代码(也防止sql注入式攻击,可以用于业务逻辑层,但要求UI层输入数据时候进行解码)
        ///
        /// 提取字符固定长度,by fangbo.yu 2008.07.18
        ///
        ///
        ///
        ///
        public string CheckStringLength(string inputString, Int32 maxLength)
        {
            if ((inputString != null) && (inputString != String.Empty))
            {
                inputString = inputString.Trim();

                if (inputString.Length > maxLength)
                    inputString = inputString.Substring(0, maxLength);
            }
            return inputString;
        }

        ///
        /// 将输入字符串中的sql敏感字,替换成"[敏感字]",要求输出时,替换回来,by fangbo.yu 2008.07.21
        ///
        ///
        ///
        public string MyEncodeInputString(string inputString)
        {
            //要替换的敏感字
            string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\*|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";
            try
            {
                if ((inputString != null) && (inputString != String.Empty))
                {
                    string str_Regex = @"\b(" + SqlStr + @")\b";
                   
                    Regex Regex = new Regex(str_Regex,RegexOptions.IgnoreCase);
                    //string s = Regex.Match(inputString).Value;
                    MatchCollection matches = Regex.Matches(inputString);
                    for (int i = 0; i < matches.Count; i++)
                        inputString = inputString.Replace(matches[i].Value, "[" + matches[i].Value + "]");
                 
                }
            }
            catch
            {
                return "";
            }
            return inputString;

        }

        ///
        /// 将已经替换成的"[敏感字]",转换回来为"敏感字",by fangbo.yu 2008.07.21
        ///
        ///
        ///
        public string MyDecodeOutputString(string outputstring)
        {
            //要替换的敏感字
            string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\*|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";
            try
            {
                if ((outputstring != null) && (outputstring != String.Empty))
                {
                    string str_Regex = @"\[\b(" + SqlStr + @")\b\]";
                    Regex Regex = new Regex(str_Regex,RegexOptions.IgnoreCase);
                    MatchCollection matches = Regex.Matches(outputstring);
                    for (int i = 0; i < matches.Count; i++)
                        outputstring = outputstring.Replace(matches[i].Value, matches[i].Value.Substring(1, matches[i].Value.Length - 2));
                 
                }
            }
            catch
            {
                return "";
            }
            return outputstring;
        }
        #endregion
 

 我们的解决方式是:

1、首先在UI录入时,要控制数据的类型和长度、防止SQL注入式攻击,系统提供检测注入式攻击的函数,一旦检测出注入式攻击,该数据即不能提交;
2、业务逻辑层控制,通过在方法内部将SQL关键字用一定的方法屏蔽掉,然后检查数据长度,保证提交SQL时,不会有SQL数据库注入式攻击代码;但是这样处理后,要求UI输出时将屏蔽的字符还原。因此系统提供屏蔽字符 的函数和还原字符的函数。
3、在数据访问层,绝大多数采用存储过程访问数据,调用时以存储过程参数的方式访问,也会很好的防止注入式攻击。

posted on 2009-09-02 14:51  欣路历程  阅读(3379)  评论(0编辑  收藏  举报

导航