首先,先声明一下,这个办法是我WoW时候忽然想出来的,绝不会完美。其次,说明一下我的方法的大致思想:判断最后要提交到数据库的SQL,通过禁止某些可能具有危害性的SQL的执行而达到防止SQL注入的目的。判断每个QueryString是很麻烦的(至少像我这种懒人觉得麻烦),而只判断最后那句SQL要简单很多。并且可以做个通用的函数,简单地调用一下即可。
先研究一下可能的SQL注入的特点。如果什么安全措施也不做,那么最后提交到数据库的SQL很可能是这样:http://www.abcdefg.com/type.asp?id=6;update admin set password='helloworld' where username='admin'--  
Select * from abc where id = 6 ;update admin set password ='helloworld' where username='admin'--那么应对措施如下:
1) 判断SQL中有没有注释符号
  自己写的SQL还用得着注释?并且注释居然不是写在代码里而是写在SQL里?先汗一下。在SQL中出现注释符号的直接pass,这必然不是什么好东西。  if ( sql.Contain("--") ) throw new Exception("SQL injection!");2) 判断SQL是不是一句话
  上例中因为有; 的存在而使本来好好的一个查询变成了两句话,而第二句话基本上就不会是什么好东西了。我可以通过判断这个SQL中有没有;的存在来判断这句SQL是不是一句话。  if ( sql.Contain(";") ) throw new Exception("SQL Injection!");3) 很有可能这些危险的符号是用十六进制存放的,那么就需要翻译一下。
  所谓“智者 当借力而行”,我们可以用现成的库函数来实现这个翻译过程  sql = Server.UrlDecode( sql ); // 把这句话放在 1 和 2 的前面4) 说不定在一些奇怪的查询中,;是作为关键字的一部分而存在的。但请注意,有这种需求的一般都是要接收一个字符串作为参数,那么这个正常的;应该是被包括在一对引号当中的。为了剔除这种情况,我们可以先用正则把所有的'!@#$'替换掉,再进行下一步的检测。
  sql = Regex.Replace(sql, @"\'.*\'", ""); // 把这句话放在 3 的后面  如此几步下来,类似例中给出的SQL注入就会被检测出来。完整代码;
  public class SqlDetector
  {
    public static void Detect(string sql)
    {
      sql = Regex.Replace(sql, @"\'.*\'", "");
      sql = Server.UrlDecode( sql );      if ( sql.Contain("--") ) throw new Exception("SQL injection!");
      if ( sql.Contain(";") ) throw new Exception("SQL Injection!");
    }
  }遗憾;
  对于诸如 http://www.abcdefg.com/type.asp?id=(select password from admin)-- 这样的SQL注入还没有办法,不过既然没有办法再继续 update,得到密码就得到了吧。您的密码居然还是用明文存放的?!全文完。
欢迎讨论!欢迎拍砖!

解决方案 »

  1.   

    /// <summary>
            /// 是否是SQL语句
            /// </summary>
            /// <param name="str">要检查的字串</param>
            /// <returns>bool</returns>
            public static bool IsSQL(string InPut)
            {
                Regex reg = new Regex(@"\?|select%20|select\s+|insert%20|insert\s+|delete%20|delete\s+|count\(|drop%20|drop\s+|update%20|update\s+", RegexOptions.IgnoreCase);            return reg.IsMatch(InPut); 
            }
      

  2.   

    两年前我还不知道什么是b/s...见笑见笑....ps:谢二楼的 我baidu了很久,只搜到了怎么进行sql注入,愣是没找着一篇能说明白怎么防止sql注入的...
      

  3.   

    /// <summary>
            /// 是否是SQL语句
            /// </summary>
            /// <param name="str">要检查的字串</param>
            /// <returns>bool</returns>
            public static bool IsSQL(string InPut)
            {
                Regex reg = new Regex(@"\?|select%20|select\s+|insert%20|insert\s+|delete%20|delete\s+|count\(|drop%20|drop\s+|update%20|update\s+", RegexOptions.IgnoreCase);            return reg.IsMatch(InPut); 
            }
      

  4.   

    回楼上...请给出一个可能的url,我再继续研究...谢谢 ^。^
      

  5.   

    http://www.abcdefg.com/type.asp?id=6;update admin set password='hello--world' where username='admin'
      

  6.   

    唉,我拷贝的太快了,我实在是有点轻视,呵呵。http://www.abcdefg.com/type.asp?password=hello--world
      

  7.   

    回楼上,顺便真诚地说声谢谢关注这句url翻译成sql 如下:
    select * from abc where password='hello--world' !@#$...我的判断逻辑会先把引号中包含的部分剔除掉再继续判断--的存在,所以这个问题不会造成什么麻烦^o^
      

  8.   

    很少做B/S,不明白為什么要直接提交SQL,那不是很危險嗎﹖前台只提供參數值﹐查詢過程全部放在后台,且輸出的查詢結果﹐是怎么暴露SQL的呢﹖
    請熟悉的朋友指點一下~~
      

  9.   

    http://www.abcdefg.com/type.asp?password=hello--'world'
    http://www.abcdefg.com/type.asp?type=hello;world等等。字符串常量不是中间没有'号,会有的。另外,在表、字段等等许多地方都会在名字中出现“--”、“;”号等。其实我懒得去跟你见招拆招地拼凑这个程序的质量,我只是分析你的程序的思路不是分析性的而是拼凑性的所以感觉中间随时会夹在很多漏洞。
      

  10.   

    其实很简单了,接收到参数后根据参数的类型判断一下就可以了。如果是数字型的判断是不是数字;如果是字符串的话过滤掉 “'”就可以了。传递过来的参数的类型是事先就定义好的 ?id=aa  。aa一定不会是字符串吧(GUID除外)。这样不就ok了嘛。包含在 “''”里面的除了 “'”都会被看作是字符串处理。所以过滤掉“'”(或则替换成“'”或其他的)就没有问题了。
      

  11.   

    sql参数全部用什么什么add啊,之类的实现。管它--或者'' 
    都不怕。哈。
      

  12.   

    .net里面用传参数的方式( DbCmd.Parameters.Add())来构造sql,不用拼接方式,还会出注入漏洞吗?那是不能会出注入漏洞的
      

  13.   

    我的出发点是因为我这个人很懒,不想用 Parameters.Add() 来判断每个参数,只想随便地把参数链到SQL中,最后只需要集中分析一下那句SQL就可以了。并且,“坚持”使用Parameters.Add()是很危险的,因为我坚持了,别人可能挺不住,那就麻烦了~~~ :)我现在规定所有的SQL都必须提交给一个底层类让它去执行,把这个判断逻辑放在那个底层类中,这样似乎可以少操不少心吧?呵呵~~
      

  14.   

    1、参数
    2、(int)Request.QueryString之类的
      

  15.   

    以前我写过一个注SQL的工具,基本现有的注入都能实现,lz有兴趣可以pm我邮箱