忽然想到的一个极其简单的防止SQL注入的办法(只针对部分有效),请大家拍砖
首先,先声明一下,这个办法是我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,得到密码就得到了吧。您的密码居然还是用明文存放的?!
全文完。
欢迎讨论!欢迎拍砖!
[解决办法]
/// <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);
}
[解决办法]
我扫了一下每一小节的标题,没有仔细看。
我感觉你忘记了一件重要的事情:你如何防止把本不是注入的东西误判为注入?!
[解决办法]
我觉得只要每次记取存入数据库的时候坚持用参数
这种攻击就不容易了
[解决办法]
很少做B/S,不明白為什么要直接提交SQL,那不是很危險嗎﹖前台只提供參數值﹐查詢過程全部放在后台,且輸出的查詢結果﹐是怎么暴露SQL的呢﹖
請熟悉的朋友指點一下~~
[解决办法]
其实很简单了,接收到参数后根据参数的类型判断一下就可以了。
如果是数字型的判断是不是数字;
如果是字符串的话过滤掉 “ '”就可以了。
传递过来的参数的类型是事先就定义好的 ?id=aa 。aa一定不会是字符串吧(GUID除外)。
这样不就ok了嘛。
包含在 “ ' '”里面的除了 “ '”都会被看作是字符串处理。所以过滤掉“ '”(或则替换成“'”或其他的)就没有问题了。
[解决办法]
sql参数全部用什么什么add啊,之类的实现。
管它--或者 ' '
都不怕。哈。
[解决办法]
.net里面用传参数的方式( DbCmd.Parameters.Add())来构造sql,不用拼接方式,还会出注入漏洞吗?那是不能会出注入漏洞的