1.关于SQL Injection
迄今为止,我基本没有看到谁写出一篇很完整的文章,或者说很成熟的解决方案(能做到 的人肯定很多,问题是没有流传开来,很遗憾) 我简单的说几点,希望启发大家思考,起到抛砖引玉的作用
 
一、SQL Injection的原理
SQL Injection的实现方法和破坏作用有很多,但万变不离其宗,其原理可以概括为一句话 :SQL Injection就是向服务器端提交事先准备好的数据,拼凑出***者想要的SQL语句,以改变数据库操作执行计划。

我想,这么说也许不算精炼,但意思应该很明确了,这句话主要包含这么三层意思:
1.***者通过何种途径注入?
存在SQL Injection漏洞的地方都是应用程序需要根据客户端环境构造SQL语句的地方。由此可以推论,只要存在"客户端数据替换预定义变量"的地方,就有可能被注入。
客户端提交数据可以有很多种方式:GET,POST,Client-Agent,Cookie,Server Enviroment...

2.***者为什么可以将它想要的语句"注入"?
因为服务器端应用程序采用拼凑(请特别留意这个词)SQL语句的方式,这使得***者有机会在提交的数据中包含SQL关键字或者运算符,来构造他们想要的语句。

3.SQL Injection最终结果是什么?
改变数据库操作执行计划。
这个结果不一定是恶意的,只要你的SQL语句没有按照你预期的计划(plan)执行,那么就 可以视为被注入了,不管提交数据的人是不是恶意的。
设有这样的sql语句:
update tableName set columnName1 = " $Client_Submit_Data " where PK_ID = 1234
$Client_Submit_Data是一个变量,它代表客户端提交的数据,这里我就不管环境是ASP还 是PHP还是其他什么东西了。
假设这个操作是要更新一篇文章的标题,很多人是不是会这么构造SQL语句?我们看看$Cl ient_Submit_Data包含引号的情况,令$Client_Submit_Data = 谁能告诉我"sql injecti on"是什么?
那么sql语句将被拼凑成这样:
update tableName set columnName1 = "谁能告诉我"sql injection"是什么?" where PK_ID = 1234
执行结果很明显,将执行这样的语句:update tableName set columnName1 = "谁能告诉我"
where子句被忽略掉了,很遗憾,你的数据库中所有文章标题都会被update为"谁能告诉我 "
 
在这个例子当中,用户应该是无心的——标题里面包括引号应该很正常吧——但结果却和SQL Injection无异。
好啦,说了半天废话,言归正传,说一下如何应对这种问题。
 
我相信这里的朋友都看过很多防止SQL Injection的文章了,也大都会通过replace来防范一些注入,问题是:你们知其然的时候是否知其所以然?
我认为,彻底解决SQL Injection的最好方法是:避免拼凑SQL语句。这就是我在上面要大家特别注意拼凑这个词的原因。

SQL Injection之所以有机可乘,是因为绝大多数Server Application采用拼凑SQL语句的方式来构建应用程序(阅读这个帖子的诸位,你们回首想想自己的项目,有几个不是通过拼凑SQL语句的方式来操作数据库?想想你们见过的被注入的案例,有几个不是采用的拼凑SQL语句的应用),所谓拼凑SQL语句,简单一点说就是:用连接字符串操作(ASP中的&和PHP中的.)将SQL关键字和客户端提交的数据连接起来并发送给DBMS执行。这样做直接导致 DBMS根本不知道你计划(plan to)做什么,而只知道你要(is to)做什么,不是吗,服务器端脚本总是将要执行的SQL语句构造好,然后发给数据库,DBMS根本不知道客户端数据 替换了变量之后,这个语句的执行计划是否有变化。服务器端脚本总是粗暴的告诉DBMS:你只管这么做好了,别问我为什么。就像上面我提到的更新文章标题的例子,DBMS不知道你只想更新第1234篇文章的标题,它以为你就是要把所有的标题都变成这个,因为你的语句就是没有where子句嘛!
 
说到这里,可能大家都明白了,所谓的最好方法是Stored Procedure。Yes! That is!
要想做出安全可靠的Server application,你最好把自己当作两个人,一个DBA,一个Coder(ASP Coder,PHP Coder or others),很多人往往只知道:我在做一个BBS,我在做一个留言本,我在做一个新闻发布系统,我们的流程都是这样的,给用户一个表单,让用户提交,然后去写数据库,用的时候根据条件把数据记录找出来,然后显示。没事,如果你 是一个业余爱好者,只想自己写点小东西玩玩,这足够了!如果你想把WebDev作为你的职业,或者说,你想成为一个非常专业的业余爱好者,你必须当自己是一个DBA+Coder,至于要不要是一个Designer就看你的能力和精力咯!
 
好了,点到为止,我就说这么多,彻底的解决方法是要在DBMS上写入你的数据操作计划,让服务器在开始执行之前知道你的意图,不要粗暴的告诉它:我就是要你执行这个命令,不要问我为什么!
 
实现方法嘛,目前比较普遍的,也比较容易实现的就是存储过程了,应用存储过程不仅可以从根本上解决SQL Injection这个安全问题,还会使得你的应用程序速度成倍增长(这个增长的幅度甚至可能达到一个数量级,这跟很多因素有关,不好一概而论),还会使得你开发的系统更想大型系统,拥有更好的架构体系(例如MVC模式)。
 
在 MySQL 4.1.x及其后续版本和ODBC中,提供了一种叫做prepared statements的东西,它 本质上也是一种存储过程,一种系统预置(相对于用户自定义)的存储过程。
如果你没有条件用上存储过程(比如数据库不支持,MySQL,Access,SQLite等都不支持),那么就只能将SQL Injection扼杀在摇篮里了。解决方法,我也只简单的说一句:不要相信任何来自客户端的数据。这个客户端的数据,可以通过很多途径被提交,比如get,post ,cookie,browser参数,IP地址,等等,只要不是服务器上获取的就都算客户端数据,只要是客户端数据,都是不可信的,在TCP/IP这个大框架下,什么都是可以伪造的,包括IP地址。
 
凡是来自客户端的数据,必须校验——注意是校验,不是过滤。基本上,不管你多聪明多细心(哪怕像我一样,不许笑,不许笑,严肃点,严肃点,我们这儿讲SQL Injection呢) 也无法穷举可能被用于SQL Injection的符号和关键字,也无法预知替换掉他们是否会有副 作用,最好的办法是不去判断什么数据不符合条件,而改由判断什么数据符合条件,假设你的一个系统用户名只能是字母数字和下划线,那么你就可以用[0-9a-zA-Z_]+这个正则来匹配它,如果不符合条件,拒之即可,这比费尽心思去过滤单引号分号逗号空格什么的要明了和简洁的多。
当然如果你嫌存储过程麻烦,你也可以使用参数化SQL语句,至少在asp.net可以这么做,请见本人的一篇文章:《在ADO.NET中使用参数化SQL语句的大同小异》,网址是:http://blog.csdn.net/zhoufoxcn/archive/2008/03/19/2195618.aspx,介绍在asp.net中使用参数化SQL语句应注意的事项。
 
春节前夕,数万个用PHPBB作为论坛的网站被攻陷,大家有印象吗?罪魁祸首只是一个单引 ,尽管PHP有magic_quotes_gpc,可还是被干掉了,原因是%2527在url_decode函数中会被解析为%27(因为%25就是百分号),%27正是引号,By the way,尽管博客中国的论坛也 是基于PHPBB的,但是那次我们幸免于难,因为在那之前我们被黑过一次了(汗),就是因为这个,哈哈! 其实,SQL Injection不是ASP编程领域特有的,Web开发最容易碰到,但Desktop Application也有,只要有数据库的地方,只要采用拼凑SQL语句的方式,就可能存在Injection的机会,大家牢记,如果有条件,尽量把数据DBMS职责范围的事情交给DBMS去做,如果没条件,一定要注意校验客户端提交的数据,当然,双管齐下也行,^_^
 
好了,最后,说句话给那些有志于从事WebDev工作的朋友,如果将来你进入这个领域,你把总结出来这篇文章,你应该会很顺利的通过面试,并得到一个不错的薪水等级。
 
附:微软发布3款SQL Injection***检测工具
随着 SQL INJECTION ***的明显增多,微软近日发布了三个免费工具,帮助网站管理员和检测存在的风险并对可能的***进行拦截。
 
这个微软和 HP合作开发的工具,会在网站中爬行,对所有网页的查询字符串进行分析并发现其中的 SQL INJECTION 风险。Scrawlr 使用了部分 HP WebInspect  相同的技术,但只检测 SQL INJECTION 风险。Scrawlr 从一个起始 URL 入口,爬遍整个网站,并对站点中所有网页进行分析以找到可能存在的漏洞。
 
这款被称作 MSCASI 的工具可以检测 ASP 代码并发现其中的 SQL INJECTION 漏洞(ASP 代码以 SQL INJECTION 漏洞著称),你需要向 MSCASI 提供原始代码,MSCASI 会帮你找到存在风险的代码位置。
 
该工具会让 IIS 限制某些类型的 HTTP 请求,通过对特定 HTTP 请求进行限制,可以防止某些有害的请求在服务器端执行。UrlScan 通过一系列关键词发现恶意请求,并阻止恶意请求的执行。