1550076451 3 年之前
父节点
当前提交
33c6e79edd

+ 1 - 0
RMYY_CallCenter_Api.Utility/RMYY_CallCenter_Api.Utility.csproj

@@ -92,6 +92,7 @@
92 92
     <Compile Include="Extention\Json.cs" />
93 93
     <Compile Include="Properties\AssemblyInfo.cs" />
94 94
     <Compile Include="RequestString.cs" />
95
+    <Compile Include="SqlChecker.cs" />
95 96
     <Compile Include="Time\DateTimeConvert.cs" />
96 97
     <Compile Include="Tree\Tree.cs" />
97 98
     <Compile Include="Tree\TreeModel.cs" />

+ 191 - 0
RMYY_CallCenter_Api.Utility/SqlChecker.cs

@@ -0,0 +1,191 @@
1
+
2
+using System;
3
+using System.Collections.Generic;
4
+using System.IO;
5
+using System.Linq;
6
+using System.Text;
7
+using System.Web;
8
+
9
+namespace RMYY_CallCenter_Api.Utility
10
+{
11
+   public  class SqlChecker
12
+    { //当前请求对象
13
+        private HttpRequest request;
14
+        //当前响应对象
15
+        private HttpResponse response;
16
+        //安全Url,当出现Sql注入时,将导向到的安全页面,如果没赋值,则停留在当前页面
17
+        private string safeUrl = String.Empty;
18
+
19
+        //Sql注入时,可能出现的sql关键字,可根据自己的实际情况进行初始化,每个关键字由'|'分隔开来
20
+        //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";
21
+        private const string StrKeyWord = @"select|insert|delete|from|drop table|update|truncate|exec master|netlocalgroup administrators|:|net user|or|and";
22
+        //Sql注入时,可能出现的特殊符号,,可根据自己的实际情况进行初始化,每个符号由'|'分隔开来
23
+        private const string StrRegex = @"-|;|,|/|(|)|[|]|}|{|%|@|*|!|'";
24
+        //private const string StrRegex = @"=|!|'";
25
+        public SqlChecker()
26
+        {
27
+            //
28
+            // TODO: 在此处添加构造函数逻辑
29
+            //
30
+        }
31
+        /// <summary>
32
+        /// 由此构造函数创建的对象,在验证Sql注入之后将停留在原来页面上
33
+        /// </summary>
34
+        /// <param name="_request">当前请求的 Request 对象</param>
35
+        /// <param name="_response">当前请求的 Response 对象</param>
36
+        public SqlChecker(HttpRequest _request, HttpResponse _response)
37
+        {
38
+            this.request = _request;
39
+            this.response = _response;
40
+        }
41
+        /// <summary>
42
+        /// 由此构造函数创建的对象,在验证Sql注入之后将请求将导向由 _safeUrl 指定的安全url页面上
43
+        /// </summary>
44
+        /// <param name="_request">当前请求的 Request 对象</param>
45
+        /// <param name="_response">当前请求的 Response 对象</param>
46
+        /// <param name="_safeUrl">验证Sql注入之后将导向的安全 url</param>
47
+        public SqlChecker(HttpRequest _request, HttpResponse _response, string _safeUrl)
48
+        {
49
+            this.request = _request;
50
+            this.response = _response;
51
+            this.safeUrl = _safeUrl;
52
+        }
53
+        /// <summary>
54
+        /// 只读属性 SQL关键字
55
+        /// </summary>
56
+        public string KeyWord
57
+        {
58
+            get
59
+            {
60
+                return StrKeyWord;
61
+            }
62
+        }
63
+        /// <summary>
64
+        /// 只读属性过滤特殊字符
65
+        /// </summary>
66
+        public string RegexString
67
+        {
68
+            get
69
+            {
70
+                return StrRegex;
71
+            }
72
+        }
73
+        /// <summary>
74
+        /// 当出现Sql注入时需要提示的错误信息(主要是运行一些客户端的脚本)
75
+        /// </summary>
76
+        public string Msg
77
+        {
78
+            get
79
+            {
80
+                string msg = "<script type='text/javascript'> "
81
+                + " alert('请勿输入非法字符!'); ";
82
+
83
+                if (this.safeUrl == String.Empty)
84
+                    msg += " window.location.href = '" + request.RawUrl + "'";
85
+                else
86
+                    msg += " window.location.href = '" + safeUrl + "'";
87
+
88
+                msg += "</script>";
89
+                return msg;
90
+            }
91
+        }
92
+        /// <summary>
93
+        /// 检查URL参数中是否带有SQL注入的可能关键字。
94
+        /// </summary>
95
+        /// <returns>存在SQL注入关键字时返回 true,否则返回 false</returns>
96
+        public bool CheckRequestQuery()
97
+        {
98
+            bool result = false;
99
+            if (request.QueryString.Count != 0)
100
+            {
101
+                //若URL中参数存在,则逐个检验参数。
102
+                foreach (string queryName in this.request.QueryString)
103
+                {
104
+                    //过虑一些特殊的请求状态值,主要是一些有关页面视图状态的参数
105
+                    if (queryName == "__VIEWSTATE" || queryName == "__EVENTVALIDATION")
106
+                        continue;
107
+                    //开始检查请求参数值是否合法
108
+                    if (CheckKeyWord(request.QueryString[queryName]))
109
+                    {
110
+                        //只要存在一个可能出现Sql注入的参数,则直接退出
111
+                        result = true;
112
+                        break;
113
+                    }
114
+                }
115
+            }
116
+            return result;
117
+        }
118
+        /// <summary>
119
+        /// 检查提交表单中是否存在SQL注入的可能关键字
120
+        /// </summary>
121
+        /// <returns>存在SQL注入关键字时返回 true,否则返回 false</returns>
122
+        public bool CheckRequestForm()
123
+        {
124
+            bool result = false;
125
+            if (request.Form.Count > 0)
126
+            {
127
+                //若获取提交的表单项个数不为0,则逐个比较参数
128
+                foreach (string queryName in this.request.Form)
129
+                {
130
+                    //过虑一些特殊的请求状态值,主要是一些有关页面视图状态的参数
131
+                    if (queryName == "__VIEWSTATE" || queryName == "__EVENTVALIDATION")
132
+                        continue;
133
+                    //开始检查提交的表单参数值是否合法
134
+                    if (CheckKeyWord(request.Form[queryName]))
135
+                    {
136
+                        //只要存在一个可能出现Sql注入的参数,则直接退出
137
+                        result = true;
138
+                        break;
139
+                    }
140
+                }
141
+            }
142
+            return result;
143
+        }
144
+        /// <summary>
145
+        /// 检查_sword是否包涵SQL关键字
146
+        /// </summary>
147
+        /// <param name="_sWord">需要检查的字符串</param>
148
+        /// <returns>存在SQL注入关键字时返回 true,否则返回 false</returns>
149
+        public bool CheckKeyWord(string _sWord)
150
+        {
151
+            bool result = false;
152
+            //模式1 : 对应Sql注入的可能关键字
153
+            string[] patten1 = StrKeyWord.Split('|');
154
+            //模式2 : 对应Sql注入的可能特殊符号
155
+            string[] patten2 = StrRegex.Split('|');
156
+            //开始检查 模式1:Sql注入的可能关键字 的注入情况
157
+            foreach (string sqlKey in patten1)
158
+            {
159
+                if (_sWord.IndexOf(" " + sqlKey) >= 0 || _sWord.IndexOf(sqlKey + " ") >= 0)
160
+                {
161
+                    //只要存在一个可能出现Sql注入的参数,则直接退出
162
+                    result = true;
163
+                    break;
164
+                }
165
+            }
166
+            //开始检查 模式1:Sql注入的可能特殊符号 的注入情况
167
+            foreach (string sqlKey in patten2)
168
+            {
169
+                if (_sWord.IndexOf(sqlKey) >= 0)
170
+                {
171
+                    //只要存在一个可能出现Sql注入的参数,则直接退出
172
+                    result = true;
173
+                    break;
174
+                }
175
+            }
176
+            return result;
177
+        }
178
+        /// <summary>
179
+        /// 执行Sql注入验证
180
+        /// </summary>
181
+        public void Check()
182
+        {
183
+            if (CheckRequestQuery() || CheckRequestForm())
184
+            {
185
+                response.Write(Msg);
186
+                response.End();
187
+            }
188
+        }
189
+    
190
+}
191
+}

+ 69 - 0
RMYY_CallCenter_Api/Global.asax.cs

@@ -5,6 +5,7 @@ using System.Collections.Generic;
5 5
 using System.IO;
6 6
 using System.Linq;
7 7
 using System.Text;
8
+using System.Text.RegularExpressions;
8 9
 using System.Threading.Tasks;
9 10
 using System.Web;
10 11
 using System.Web.Mvc;
@@ -33,5 +34,73 @@ namespace RMYY_CallCenter_Api
33 34
                 System.Diagnostics.Debug.WriteLine(DateTime.Now);
34 35
             });
35 36
         }
37
+        protected void Application_AuthenticateRequest(object sender, EventArgs e)
38
+        {
39
+            SqlChecker SqlChecker = new SqlChecker(this.Request, this.Response);
40
+            SqlChecker.Check();
41
+            HttpApplication app = (HttpApplication)sender;
42
+            var context = app.Context;
43
+            if (context == null) throw new ArgumentNullException("context");
44
+
45
+            Dictionary<string, string> Params = new Dictionary<string, string>();
46
+            Params.Add("request_url", context.Request.Url.ToString());
47
+
48
+            bool issafe = true;
49
+            foreach (var key in context.Request.Params.AllKeys)
50
+            {
51
+                if (key == "ALL_HTTP")
52
+                {
53
+                    break;
54
+                }
55
+                Params.Add(key, context.Request.Params[key]);
56
+                try
57
+                {
58
+                    string paras = context.Request.Params[key].ToString();
59
+                    if (!paras.Contains("data:image/png;base64,"))
60
+                    {
61
+                        SqlFilter(paras);
62
+                    }
63
+                }
64
+                catch
65
+                {
66
+                    issafe = false;
67
+                    break;
68
+                }
69
+            }
70
+            if (!issafe)
71
+            {
72
+                context.Response.Write(new AjaxResult { state = ResultTypes.error.ToString(), message = "非法输入!" }.ToJson());
73
+                context.Response.End();
74
+            }
75
+
76
+            
77
+        }
78
+
79
+        /// <summary>
80
+        /// 检查危险字符
81
+        /// </summary>
82
+        /// <param name="Input"></param>
83
+        /// <returns></returns>
84
+        public static string SqlFilter(string sInput)
85
+        {
86
+            if (sInput == null || sInput == "")
87
+                return null;
88
+            string sInput1 = sInput.ToLower();
89
+            string output = sInput;
90
+            //去掉星号*
91
+            //string pattern = @"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";
92
+            string pattern = @"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";
93
+            if (Regex.Match(sInput1, @"\b(" + pattern + @")\b", RegexOptions.Compiled | RegexOptions.IgnoreCase).Success)
94
+            {
95
+                throw new Exception("字符串中含有非法字符!");
96
+            }
97
+            else
98
+            {
99
+                output = output.Replace("'", "''");
100
+            }
101
+            return output;
102
+        }
103
+
104
+
36 105
     }
37 106
 }