标题：注入漏洞
定义
这个漏洞是现在应用最广泛，杀伤力也很大的漏洞，可以说微软的官方网站也存在着注入漏洞。注入漏洞是因为字符过滤不严谨所造成的，可以得到管理员的帐号密码等相关资料。
检测方法
目前比较准确的检测注入漏洞的方法是进行网站漏洞扫描，推荐EeSafe网站安全联盟。
查找与修补
一、注入点的查找
当我们想要测试某个站点时，一般会架上注入工具对其狂轰乱炸，这样做虽然有时能找到注入点，但还是有些盲目，我个人的看法是：如果有源码的话，就从源码入手，在源码中查找注入点。对于源码，有些朋友可能觉得很难，其实源码并不神秘，它也是有一定的语法规则的，看一套优秀的源码就像是在欣赏一部精美的电影，只要我们坚持每天看一些优秀源码，再加上百度这个老师的指点，用不了多久，源码的神秘面纱就会被你揭去。闲话少说，下面我们就开始查找注入点，目标有两个：一是Request，二是SQL语句。
说到Request，这个是ASP程序中的一个内建对象，怎么？不懂？那就跟我先来恶补一下吧！它是用来获取客户端信息的，有五种方法，而会出现注入点的一般有以下三种：
1、Request.QueryString：取得客户端提交的信息。当Form以Get方法提交信息，或是直接在URL中提交变量值时，在服务器端接收数据时采用的就是这种方法。
2、Request.Form：同样也是取得客户端提交的信息，但它接收的是Form以Post方法提交的信息。
3、Request.Cookies：取得客户端浏览器的Cookies信息。Cookies就是小甜饼，指的是一些私人信息，如用户名、密码之类的信息。
有些程序员为了减少错误，对于前两种信息的获取，会采用Request来取得客户端提交的信息，这种方法，虽然可以通吃Request.QueryString和Request.Form的提交信息，但如果过滤的不好，就会被漏洞反咬一口。
了解过一些Request的知识后，下面就在“查找”中输入“request”进行搜索，OK！当找到上面所列的三项Request语句后，再来看一下程序对这些Request语句是否做了过滤，比如ID值是否用INT过滤，例：id=int(request("id"))；字符串值是否用replace ()或instr()等函数进行过滤单引号或一些特殊字符，例：username=replace(request("username"),"", "")；或者程序是否采用本身的一些过滤函数来过滤这些提交值。从查找到这句request参数起，一直到SQL语句中使用这个提交值至，如果中间没有上面的层层关卡，那么，一个注入点，基本上就算是出现了。
说到SQL语句，不能不提到以下几个常用的语句：
1、查询语句：Select [(<字段名1> [,<字段名2>, ...])] FROM <表名JMDCW> [Where <条件表达式> [AND|OR <条件表达式>...]
2、更新语句：Update <表名JMDCW> SET 列名1 = 常量表达式1[,列名2 = 常量表达式2 ...] Where <条件表达式> [AND|OR <条件表达式>...]
3、删除语句：Delete FROM〈表名JMDCW〉[Where <条件表达式> [AND|OR <条件表达式>...]]
这里不对SQL语句做介绍了。在上面列出的SQL语句中，注入点出现频率最高的是Select语句，而注入参数的出没地通常都是在Where之后的条件中。当一个没有过滤的Request语句进入SQL语句后，就是注入大显身手的时候了，不过，在进行注入之前还要先看一下该参数是直接引入，还是用单引号引入的，另外，该参数是否还应用于其他SQL语句中，然后，根据不同的信息，选择不同的处理方式，或直接暴破，或UNION查询，当然，如果存在注入点的程序使用的是SQL数据库，那就不单单是得到一些重要信息，甚至还可以增加管理员。
下面用“蚂蚁影院3.0”版注销用户(wantlogin.asp)中的一段源码来做一下介绍：
引用
<%
if request("userid1")<>"" then 
set rst=server.createobject("adodb.recordset")
sql="select money,online from users where userid="&request("userid1")&" and password="&md5(request("pws"))&""
rst.open sql,conn,1,3
if rst.eof and rst.bof then
response.write"<script>alert(用户名或密码错误！);history.back();</Script>"
else
response.write"<script>alert(恢复成功你现在可以登陆！);</Script>"
response.write"<script Language=Javascript>location.href = index.asp;</script>"
rst.close
set rst=nothing
conn.close
set conn=nothing
end if
end if
%>
在其流程中，首先判断取得的提交值userid1是否为空，不为空的话就进入SQL语句中，验证取得的用户名及密码是否和数据库内的用户名及密码一致，如果不一致，则弹出“用户名及密码错误”窗口，否则，就弹出“恢复成功”的窗口。这也是一段典型的注入漏洞源码，并且，接收的方式还是使用的 request，这就给我们提交注入语句提供了最大的方便。如果我们在URL地址中提交如下字符：http: //127.0.0.1/wantlogin.asp?userid1=aa&pws=bb，因为没有aa这个用户，那么就会弹出错误窗口，而如果我们将aa换成如下字符：aa or　1=1 or 1=1，pws保持不变，这样提交的语句到了SQL语句中就成了如下语句：
select money,online from users where userid1=aa or 1=1 or 1=1 and password=md5(bb)，以往我们所见到的测试代码一般为“or 1=1”，而这里却多用了一个 or ，为什么要多用一个or呢？解释一下，在逻辑运算符中，and的优先级别高于or ，程序运行后会先运算后面的1=1 and password=md5(bb)，因为密码是随便输入的，所以and后的password值为假，而and前的1=1虽然为真，但真and 假=假，所以，这个and的运算值为假，再来看or运算，因为前面的用户名也是不存在的，其值当然为假，如此一来，where后的逻辑运算就成了如下表达式：假or真or假，结果值还是为真，这样就会弹出“恢复成功”窗口，如果将其中的or 1=1 改为or 1=2，那逻辑表达式则成了：假or假or假，值当然也为假，弹出的就是“用户名或密码错误”的窗口。这样，根据弹出窗口的不同，我们就可以构造一些特殊字符，然后猜测出需要的数据了，比如查询管理员ID的语句，将or后的1=1更改为： 1=(Select top 1 id from admin)，这里暂用admin表示管理员表名，如果存在ID为1的管理员，那么就会弹出“恢复成功”的窗口，否则，就证明管理员的ID不为1，那就要再用其他数字来测试。猜出管理员ID后，再把此段字符更改为猜测管理员名称长度的字符：5<(Select len(adminname) from admin where id=1)，如为真，则证明长度大于5，否则长度小于或等于5。猜出长度后，再用asc()函数来猜测管理员的名称：90<(select asc(mid(adminname,1,1)) from admin where id=1)，如此循环，就能暴破出管理员的名称及密码了。
上面提到的是Request.QueryString和Request.Form的注入方法，而Request.Cookies的注入方法则是要修改本地的Cookies值来实现的，推荐使用一些专门的Cookies修改工具，不过，用Cookies来注入相对而言，就麻烦了好多，但原理和前面的注入是一样的，这里就不介绍了。
二、注入点的修补
在上面着重讲了如何查找注入点及简单的利用方法，当我们知道了攻后，也就明白了如何守，攻和守之间虽然是对立的，但也是相互的。明白了什么地方存在注入点，再来修补也就容易多了。在前面查找注入点时，我也提到查看程序中是否对提交参数进行了过滤，每个程序对注入的过滤函数都不相同，我们在修补自已站点上的注入点时，可参照其他程序中的过滤函数，也可根据自已的需要，单独过滤一些敏感的字符。这里，还是以上面的那个例子来说一下如何修补注入点。在前面的 SQL语句中有这一句：userid="&request("userid1")&"，这其中对提交来的参数是用单引号来引入的，而我们能成功注入也是在提交参数中加入了单引号来闭合其语句，这样，加入一个replace()函数对单引号进行过滤，修改后的语句为：userid= "&replace(request("userid1"),"","")&"，这样用户再提交带有单引号的字符时， Replace()就会将单引号过滤为空，如此一来，提交的那些特殊字符也就失去了其意义。
当然，我们还可以在userid1进入SQL语句之前，对其长度进行一下判断，如果超过规定的长度，就弹出错误，中止页面执行并返回到指定的页面。当然还可以借鉴一些优秀源码中的过滤方法。总之，注入漏洞是可以避免的，即使出现了注入点，只要我们分析出其出现的原因，也就能很容易地将其修补了！