T-SQL篇如何防止SQL注入的解决方法

所属分类: 数据库 / MsSql 阅读数: 254
收藏 0 赞 0 分享
1.什么是SQL注入
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。

2.怎么进行SQL注入
关于怎么进行SQL注入,网上已经有很多文章详细介绍过了,可以参考博友滴答的雨的博文 《SQL注入攻防入门详解》,亲测有效。当执行完文中的5、6、7三步的时候,你会发现服务器上的安全保护措施都已是浮云,服务器也因此变成了名副其实的“肉机”。下面附上一张我在本机执行完文中描述的脚本后的效果截图(Win8 x64 操作系统):

image
微软的“不禁止即允许(Not forbidden is allow)”的做法使得操作系统像是服务器所穿的镂空礼物一样,美观但却有很多“漏洞”。好了,现在此小黑已经拥有了服务器的管理员权限,很显然元芳怎么看已经不重要了。

3.如何防止SQL注入的发生
滴答的雨已经在博文详细阐述了SQL Server数据库如何进行防注入的操作,这里不再赘述。这一篇我主要说一下对于一个使用拼接SQL进行查询操作的Web应用,怎么进行防注入操作。
先说一些前提,为什么我们要使用拼接SQL的方式进行查询?偷懒呗。这在开发过程中,看似省去了编写参数化部分的代码量,节省了时间和精力。但这样做的结果就是应用的安全性大打折扣,而且拼SQL方式创建的应用,后期的维护难度也很大。SQL参数化查询是最简单有效的避免SQL注入的解决方案,目前主流的ORM框架(MyBatis.NET/NHibernate/EntityFramework)都内置支持并且推荐使用这种方式进行持久层封装。

然而有数据库不支持参数化查询怎么办?是的,你没有看错,确实有这样的数据库存在。吐个槽先,个人认为,一切不支持参数化查询的数据库都是在“耍流氓”,这种天然的缺陷会让小黑们肆无忌惮地去“非礼”服务器,至少是数据库本身。在这样的情况下,我觉得其他功能做得再好也只能算是花拳绣腿,连最基本的数据都保护不了,那不等同于将劳动成果拱手让人。按照存在即合理的逻辑,我们暂且认为它是合理的。

来说说我目前的做法,基于上述数据库创建的Web应用,拼接SQL操作已经渗透到站点的每个页面、每个用户控件,所以我采用的方式是请求过滤。
下面是防SQL注入的操作类:

 1: /// <summary>
 2:  ///SqlInject 的摘要说明
 3:  /// </summary>
 4:  public class SqlInject : System.Web.UI.Page
 5:  {
 6:   //检测到注入后的处理方式: 0:仅警告;1:警告+记录;2:警告+自定义错误页面;3:警告+记录+自定义错误页面
 7:   private const int _type = 0;
 8:   private const string errRedirectPage = "/err.aspx";
 9:  
 10:   //如果记录注入信息,那么请设置:errMDBpath:数据库路径
 11:   private const string errMDBpath = "/SqlInject.mdb";
 12:  
 13:  
 14:   //过滤特征字符
 15:   //过滤特征字符
 16:   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";
 17:   private static string StrRegex = ConfigurationManager.AppSettings["SqlRegex"];  //@";|/|(|)|[|]|{|}|%|@|*|'|!"; // 原始过滤条件:【-|;|,|/|(|)|[|]|{|}|%|@|*|'|!】
 18:  
 19:   private HttpRequest request;
 20:   public SqlInject(System.Web.HttpRequest _request)
 21:   {
 22:    this.request = _request;
 23:   }
 24:   ///<summary>
 25:   ///检测SQL注入及记录、显示出错信息
 26:   ///</summary>
 27:   public void CheckSqlInject()
 28:   {
 29:    bool isInject = false;
 30:    if (CheckRequestQuery() || CheckRequestForm())
 31:    {
 32:     isInject = true;
 33:    }
 34:    else
 35:    {
 36:     return;
 37:    }
 38:  
 39:    switch (_type)
 40:    {
 41:     case 0:
 42:      ShowErr();
 43:      break;
 44:     case 1:
 45:      ShowErr();
 46:      SaveToMdb();
 47:      break;
 48:     case 2:
 49:      ShowErr();
 50:      string temp;
 51:      System.Web.HttpContext.Current.Response.Write("<script>setTimeout(\"" + "location.href='" + errRedirectPage + "'" + "\",5000)</script>");
 52:      break;
 53:     case 3:
 54:      ShowErr();
 55:      SaveToMdb();
 56:      System.Web.HttpContext.Current.Response.Write("<script>setTimeout(\"" + "location.href='" + errRedirectPage + "'" + "\",5000)</script>");
 57:      break;
 58:     default:
 59:      break;
 60:    }
 61:    System.Web.HttpContext.Current.Response.End();
 62:  
 63:   }
 64:   private void SaveToMdb()
 65:   {
 66:    OleDbConnection conn = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + Server.MapPath(errMDBpath));
 67:    conn.Open();
 68:    OleDbCommand cmd = conn.CreateCommand();
 69:  
 70:    cmd.CommandText = "insert into [Record] (sIP,sDate,sPath) values ('" +
 71:        request.ServerVariables["REMOTE_ADDR"].ToString() + "','" +
 72:        DateTime.Now + "','" + request.ServerVariables["URL"].ToLower() + RelaceSingleQuotes(request.QueryString.ToString()) + "')";
 73:    int code = cmd.ExecuteNonQuery();
 74:    if (code == 1)
 75:     System.Web.HttpContext.Current.Response.Write("<br>****以上信息已记录至日志数据库****");
 76:    else
 77:     System.Web.HttpContext.Current.Response.Write("<br>日志数据库出错");
 78:    conn.Close();
 79:  
 80:   }
 81:   private string RelaceSingleQuotes(string _url)
 82:   {
 83:    string URL = _url.Replace("'", "单引号");
 84:    return URL;
 85:   }
 86:   private void ShowErr()
 87:   {
 88:    //string msg = @"<font color=red>请不要尝试未授权之入侵检测!</font>" + @"<br><br>";
 89:    //msg += @"操作IP:" + request.ServerVariables["REMOTE_ADDR"] + @"<br>";
 90:    //msg += @"操作时间:" + DateTime.Now + @"<br>";
 91:    //msg += @"页面:" + request.ServerVariables["URL"].ToLower() + request.QueryString.ToString() + @"<br>";
 92:    //msg += @"<a href='#' onclick='javascript:window.close()'>关闭</a>";
 93:    //System.Web.HttpContext.Current.Response.Clear();
 94:    //System.Web.HttpContext.Current.Response.Write(msg);
 95:    System.Web.HttpContext.Current.Response.Write("<script>alert('请不要尝试未授权之入侵检测!');javascript:history.go(-1);</script>");
 96:   }
 97:   ///<summary>
 98:   /// 特征字符
 99:   ///</summary>
 100:   public static string KeyWord
 101:   {
 102:    get
 103:    {
 104:     return StrKeyWord;
 105:    }
 106:   }
 107:   ///<summary>
 108:   /// 特征符号
 109:   ///</summary>
 110:   public static string RegexString
 111:   {
 112:    get
 113:    {
 114:     return StrRegex;
 115:    }
 116:   }
                
更多精彩内容其他人还在看

SQL 提权 常用命令

SQL 提权 常用命令,大家可以考虑下将sqlserver的服务运行权限设置为普通用户,即可防止下面的提权。
收藏 0 赞 0 分享

数据转换冲突及转换过程中大对象的处理

数据转换冲突及转换过程中大对象的处理方法,大家可以参考下。
收藏 0 赞 0 分享

SQLServer 数据库开发顶级技巧

无论你的专业水平如何,从其他IT专家那里学习新的技巧与最佳实践常常都是有益的。本文包含了我遇到过的SQL Server开发的高级技巧。希望其中的一些技巧能够对您的数据库开发及管理工作有所帮助。
收藏 0 赞 0 分享

远程连接SQLSERVER 2000服务器方法

需求如下:需要远程连接外地的SQL Server 2000服务器。
收藏 0 赞 0 分享

SQLserver2000 企业版 出现"进程51发生了严重的异常"错误的处理方法

SQL2000 企业版 出现“进程51发生了严重的异常”错误的解决方法,利用了微软官方的工具。
收藏 0 赞 0 分享

SQLServer 触发器 数据库进行数据备份

首先,你需要建立测试数据表,一个用于插入数据:test3,另外一个作为备份:test3_bak
收藏 0 赞 0 分享

SQLServer 数据库备份过程中经常遇到的九种情况

SQLServer 数据库备份过程中经常遇到各种问题,大家可以参照下面的问题,来分析下,快速的解决问题。
收藏 0 赞 0 分享

SQL 截取字符串应用代码

字符串截取函数,只限单字节字符使用(对于中文的截取时遇上奇数长度是会出现乱码,需另行处理),本函数可截取字符串指定范围内的字符。
收藏 0 赞 0 分享

除MSSQL数据库text字段中恶意脚本的删方法

删除MSSQL数据库text字段的替换处理示例--全表替换,看到有人提问,所以整理了一个好久以前的处理方法,以供大家参考
收藏 0 赞 0 分享

sql 普通行列转换

说明:普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法。
收藏 0 赞 0 分享
查看更多