一、背景
在我们开发网站的时候,一般都会把管理员后台的目录命名为admin这样的,当一些别有用心的人就会去找到这样的路径进行管理员密码的暴力破解。还有一些就是暴力去探索管理员后台的登录路径,再进一步进行破解。
非常的不幸,上个月我的网站就遭到了恶运,甚至还被SQL注入的方式来试我的网站,造成我的错误日志文件有3兆那么多。
如图:
从日志的分析来看,这些一定是通过暴力的工具访问的,目的就是想得到后台登录地址。如果每天都被这样的工具来破解,那么服务器的承受压力一样非常的大。
逼于种种的担忧和压迫,最后我想了一个策略来限制这类事情的发生,那就是限制IP访问。
二、策略
当访问网站时,有错误发生,这个错误可以是错误的URL或者SQL注入的关键字,就记录访问者的IP,当恶意访问这的IP数达到一定的数目时就禁止访问。
如图:
数据库:
在Application_Error全局函数里进行用户的IP记录:
//出错时记录用户IP string ip = Request.UserHostAddress; MaliciousAccess.Service.MaliciousAccessService.Instance.Add_Entity(new Service.MaliciousAccess() { IP = ip, CreateTime = DateTime.Now }); Response.Redirect("error.html");
然后,我自定义了一个httpmodule的类来拦截所有的URL访问,在这个类中,我会先判断是否为SQL注入的URL,再来判断是否达到IP上线,因为SQL注入的方式访问网站,是不会跳到错误处理函数的。
/* ============================================================================== * 类名称 :MaliciousAccess * 类描述 : * 创建人 :Jim * 创建时间 :2013/5/3 10:35:50 * ==============================================================================*/ using System; using System.Web; using System.Data; namespace MaliciousAccess.Service { public class HttpModule : IHttpModule { private int errorcount = 20;//错误访问数 /// <summary> /// 您将需要在您网站的 web.config 文件中配置此模块, /// 并向 IIS 注册此模块,然后才能使用。有关详细信息, /// 请参见下面的链接: http://go.microsoft.com/?linkid=8101007 /// </summary> #region IHttpModule Members public void Dispose() { //此处放置清除代码。 } public void Init(HttpApplication context) { context.PreRequestHandlerExecute += new EventHandler(OnPreRequest); } #endregion public void OnPreRequest(Object source, EventArgs e) { //可以在此放置自定义日志记录逻辑 goErr(Uri.UnescapeDataString(HttpContext.Current.Request.Url.AbsoluteUri));//Sql注入IP限制 //普通错误访问IP限制 if (HttpContext.Current.Request.Url.AbsolutePath.IndexOf("Error.aspx") <= -1) { DataTable dt = Service.MaliciousAccessService.Instance.db.FromSql("select count(*) from MaliciousAccess where convert(varchar(10),CreateTime,120)='" + DateTime.Now.ToString("yyyy-MM-dd") + "' ").ToTable() as DataTable; if (int.Parse(dt.Rows[0][0].ToString()) > errorcount) { HttpContext.Current.Response.Redirect("Error.aspx"); } } } /// <summary> /// SQL注入过滤 /// </summary> /// <param name="InText">要过滤的字符串 </param> /// <returns>如果参数存在不安全字符,则返回true </returns> public bool SqlFilter(string InText) { string word = "and|exec|insert|select|delete|update|chr|mid|master|or|truncate|char|declare|join|cmd"; if (InText == null) return false; foreach (string i in word.Split('|')) { if ((InText.ToLower().IndexOf(i + " ") > -1) || (InText.ToLower().IndexOf(" " + i) > -1)) { return true; } } return false; } /// <summary> /// 校验参数是否存在SQL字符 /// </summary> /// <param name="tm"> </param> private void goErr(string tm) { if (SqlFilter(tm)) { string ip = HttpContext.Current.Request.UserHostAddress; MaliciousAccessService.Instance.Add_Entity(new Service.MaliciousAccess() { IP = ip, CreateTime = DateTime.Now }); HttpContext.Current.Response.Redirect("Error.html"); } } } }
三、总结
这样应该有效的防止恶意访问了吧,暂时只想到这种方式,如果大家有更好的方式,欢迎大家交流一下哈。
最后附上例子:(链接: https://pan.baidu.com/s/1skXeZ4x 密码: mgxz)
数据库访问组件使用的是:MySoft.Data