Dream Maker 老漂 不要有和人斗的心,你要赢的是你自己!

过滤不严格造成的漏洞解析('or'='or'原理以及修补办法)

这次先给大家介绍个脚本漏洞.

一般一个网站系统无非都是查询数据库然后生成网页,或者实现特殊功能,这里我找到一个网站.

http://www.k**e.com/admin/admin_login.asp

这里我直接猜到他的后台.

如下图所示,帐户密码那里我打了箭头,注意我输入的都是 'or'='or' 很多玩过黑客的人都会知道这个漏洞,

这里主要讲解的这个漏洞的原理.

 

 

 

 

 

 
 
登陆进入后我们看到如图
 
我们看到进入了,至于下面的步骤我们这里就不讨论了,我们看下对方的源代码分析下这个漏洞的形成原因
 
File:Admin_Login.asp
------------------------------------------------
<%option explicit%>
<!--#include file="../inc/conn.inc" -->
<!--#include file="inc/config.asp" -->
<!--#include file="inc/md5.asp" -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title><%=GetOneSet(0)%></title>
<style type="text/css">
<!--
body {
background-image: url(images/bg1.gif);
margin: 0px;
background-repeat: repeat-x;
}
table,td{
font-family:"宋体";
font-size:12px;
}
.inputtext{
border-left:1px solid balck;
border-right:1px solid balck;
border-top:1px solid balck;
border-bottom:1px solid balck;
}
.loginbg {
font-size: 12px;
width: 59px;
height: 26px;
background-image: url(images/login_bg.gif);
border: none;
padding-top: 3px;
color:white;}
-->
</style>
<%
session("admin")=false
session("pass")=false
response.Cookies("newspics")=""
Function gen_key(digits)
      dim output
      dim char_array(50)
          char_array(0)      =       "0"
          char_array(1)      =       "1"
          char_array(2)      =       "2"
          char_array(3)      =       "3"
          char_array(4)      =       "4"
          char_array(5)      =       "5"
          char_array(6)      =       "6"
          char_array(7)      =       "7"
          char_array(8)      =       "8"
          char_array(9)      =       "9"
      randomize
      do while len(output) < digits
          output = output&char_array(Int((9 - 0 + 1) * Rnd + 0))
      loop
      gen_key=output
End Function
dim key
key=gen_key(4)
dim action
action=request.QueryString("action")
if action="login" then
    dim sql,verifyCode,manager,password,key2,rs,power
    password=request.Form("txtPassword")
  manager=request.Form("txtManager")
    verifyCode=request.Form("txtVerify")
    key2=request.Form("key")
  
    password=MD5(password)
  
    if key2=verifyCode then
    sql="select * from manager where managerName='"&manager&"' and managerPassword='"&password&"'"
set rs=server.CreateObject("adodb.recordset")
rs.open sql,conn,1,1
if not rs.eof then
     session("pass")=true
     session("manager")=rs("managerName")
     session("managerId")=rs("managerId")
     power=rs("power")
     if power=1 then
    session("admin")=true
     else
    session("admin")=false
     end if
     response.Cookies("power")("power_class")=rs("power_class")
     response.Cookies("power")("power_news")=rs("power_news")
     'call GetSetting()
     action=3
    else
     session("pass")=false
     session("admin")=false
     action=2
    end if
    rs.close
    set rs=nothing
    else
      action=1
    end if
end if
conn.close
set conn=nothing
if action=3 then response.Redirect("admin_index.asp")
%>
</head>
<body>
<div align="center">
<%
if action=2 then
response.Write("用户名或密码错误,请重登陆 <br>")
elseif action=1 then
response.Write("验证码不正确,请重登陆 <br>")
end if
%>
</div>
<table width="100%" height="98" border="0" cellspacing="0" cellpadding="0">
    <tr>
      <td> </td>
    </tr>
</table>
<table width="50%" align="center" height="34" border="0" cellspacing="0" cellpadding="0">
    <tr>
      <td><img src="images/admin_02.gif" width="291" height="34"></td>
    </tr>
</table>
<table width="100%" height="30" border="0" cellspacing="0" cellpadding="0">
    <tr>
      <td> </td>
    </tr>
</table>
<table width="50%" height="261" border="0" align="center" cellpadding="0" cellspacing="0">
    <tr>
      <td valign="top"><table width="457" border="0" cellspacing="0" cellpadding="0">
        <tr>
          <td colspan="3"><img src="images/admin_05.gif" width="457" height="40" border="0" usemap="#Map" href="../index.asp"></td>
        </tr>
        <tr>
          <td width="142" rowspan="3" valign="bottom" background="images/lbg.gif"><img src="images/admin_07.gif" width="142" height="221"></td>
          <td width="240" valign="top"><img src="images/admin_08.gif" width="240" height="42"></td>
          <td width="75" rowspan="3" valign="bottom" background="images/rbg.gif"><img src="images/admin_09.gif" width="75" height="221"></td>
        </tr>
        <tr>
          <td height="107" valign="top" background="images/admin_10.gif">
    <form action="admin_login.asp?action=login" name="form1" method="post">
    <table width="75%"    align="center" height="100%" border="0" cellpadding="0" cellspacing="0">
                    <tr>
                      <td width="24%" height="30">用    户:</td>
                      <td width="76%" height="30"><input type="text" name="txtManager" id="txtManager" size="15" maxlength="20" class="inputtext"></td>
                    </tr>
                    <tr>
                      <td height="25">密    码:</td>
                      <td height="25"><input name="txtPassword" type="password" id="txtPassword" size="15" maxlength="20" class="inputtext">
                    <tr>
                      <td height="25">验证码:</td>
                      <td height="25"><input name="txtVerify" type="text" id="txtVerify" size="15" maxlength="20" class="inputtext">    <%=key%></td>
                    </tr>
                    <tr>
                      <td height="25" colspan="2"><p align="center"><input type="submit" value="登 陆" class="loginbg"><span class="mframe-t-right">
            <input name="key" type="hidden" id="key" value="<%=key%>">
            </span>    <input type="reset" value="取 消" class="loginbg"></td>
                </tr>
              </table></form></td>
        </tr>
        <tr>
          <td valign="bottom"><img src="images/admin_11.gif" width="240" height="72"></td>
        </tr>
      </table></td>
    </tr>
</table>
<map name="Map">
    <area shape="rect" coords="349,1,437,39" href="../index.asp">
</map></body>
</html>
-------------------------------------
 
看到我高亮起来的两个地方,学过动态网页的都明白这个意思,简单说下,大致意思
 
第一处,先获得传递过来的一个变量txtManager的值.
 
第二处,构造SQL查询语句查询数据库.
 
表面上看没什么问题但是我们仔细想想,程序并没有规定我必须输入什么数据,我可以构造一个特殊的数据
 
当我两个都输入的是 'or'='or' 的时候我们复原下SQL语句看看
 
select * from manager where managerName='"&manager&"' and managerPassword='"&password&"'
 
这里等价于
 
select * from manager where managerName='' or '=' or '' and managerPassword='"&password&"'
 
这里这句逻辑上不好想,我们换个用户和密码
 
用户:'or'1'='1'or'
密码:[随便]
 
select * from manager where managerName=''or'1'='1'or'' and managerPassword='abc'
 
我们分析下后面    where managerName='' 这里肯定是 False 但是后面跟了个 or 或者的意思后面 '1'='1' 这个肯定是真的,后面 or '' 这个或者为空肯定是 False 的,所以前面返回为真
 
那么当这个查询语句查询后是成功的,返回的Recordset里是 manager 的全部记录,当然如果为管理员信息一般只有一条.所以我们就会正常进入后台.
 
我们注意后面的代码又将查询到的信息存入了 Session 这样我们访问 admin_index.asp 的时候就不会被弹出来.
 
OK我们看到了,过滤不严格造成的网站后台登陆的漏洞,其实这个漏洞是很常见的,很多程序员不重视网站的安全性.
 
其实要防范这种漏洞很简单,既然我们已经知道了原理,那么我们很容易就可以想出对应方法
 
最简单有效的方法,加入一个过滤的函数过滤掉特殊字符.
 

Function StrCheck(fString)
fString=Trim(Server.HtmlEncode(fString))
fString=Replace(fString,"&amp;","&")'
fString=Replace(fString,"\","&#92;")
fString=Replace(fString,"--","&#45;&#45;")
fString=Replace(fString,CHR(9),"&#9;")
fString=Replace(fString,CHR(10),"<br>")
fString=Replace(fString,CHR(13),"")
fString=Replace(fString,CHR(22),"&#22;")
fString=Replace(fString,CHR(32),"&#32;")
fString=Replace(fString,CHR(39),"&#39;")'单引号
fString=Replace(fString,";","&#59;")
StrCheck=fString
End Function
 
这个函数可以过滤掉常见的一些特殊字符.
 
我们在获得变量后加一个 StrCheck(managerName) 过滤下就OK了.

第二种方法

在你的conn.asp 文件中加防注入代码就行了;这是form注入;下面是防注入代码;<%'Dim Fy_Post,Fy_Get,Fy_cook,Fy_In,Fy_Inf,Fy_Xh,Fy_db,Fy_dbstr,aa On Error Resume Next Fy_In = "'|exec|insert|select|delete|update|count|chr|truncate|char|declare|--|script|*|char|set|(|)" aa="heike.txt" '------------------------------------------如入侵记录保存文件 Fy_Inf = split(Fy_In,"|") '1--------POST部份------------------ If Request.Form<>"" Then For Each Fy_Post In Request.Form For Fy_Xh=0 To Ubound(Fy_Inf) If Instr(LCase(Request.Form(Fy_Post)),Fy_Inf(Fy_Xh))<>0 Then flyaway1=""&Request.ServerVariables("REMOTE_ADDR")&","&Request.ServerVariables("URL")&"+'post'+"&Fy_post&"+"&replace(Request.Form(Fy_post),"'","*")&"" set fs=server.CreateObject("Scripting.FileSystemObject") set file=fs.OpenTextFile(server.MapPath(aa),8,True) file.writeline flyaway1 file.close set file=nothing set fs=nothing call aaa() End If Next Next End If'2--------GET部份------------------- If Request.QueryString<>"" Then For Each Fy_Get In Request.QueryString For Fy_Xh=0 To Ubound(Fy_Inf) If Instr(LCase(Request.QueryString(Fy_Get)),Fy_Inf(Fy_Xh))<>0 Then flyaway2=""&Request.ServerVariables("REMOTE_ADDR")&","&Request.ServerVariables("URL")&"+'get'+"&Fy_get&"+"&replace(Request.QueryString(Fy_get),"'","*")&"" set fs=server.CreateObject("Scripting.FileSystemObject") set file=fs.OpenTextFile(server.MapPath(aa),8,True) file.writeline flyaway2 file.close set file=nothing set fs=nothing call aaa() End If Next Next End If'3--------cookies部份------------------- If Request.Cookies<>"" Then For Each Fy_cook In Request.Cookies For Fy_Xh=0 To Ubound(Fy_Inf) If Instr(LCase(Request.Cookies(Fy_cook)),Fy_Inf(Fy_Xh))<>0 Then flyaway3=""&Request.ServerVariables("REMOTE_ADDR")&","&Request.ServerVariables("URL")&"+'cook'+"&Fy_cook&"+"&replace(Request.Cookies(Fy_cook),"'","*")&"" set fs=server.CreateObject("Scripting.FileSystemObject") set file=fs.OpenTextFile(server.MapPath(aa),8,True) file.writeline flyaway3 file.close set file=nothing set fs=nothing call aaa() End If Next Next End IfSub aaa() Response.Write "请不要注入,我们已记下你的ip" Response.Write "<br><hr>" Response.End end Sub%>

 

第三种方法

先来了解下万能密码的产生
分析一个login.asp

(1)pwd = request.form("pwd") "获取客户端输入的密码,再把值赋给pwd"
(2)name = request.form("name")  "获取客户端输入的用户名再把值赋给name"
都没有进行任何过滤
(3)Set rs = Server.CreateObject("ADODB.Connection") "利用Server对象的CreateObject方法创建ADO组件的Connection对象"
(4)sql = "select * from Manage_User where UserName='" & name & "' And PassWord='"&encrypt(pwd)&"'"  "将用户名和密码放入查询语句中查询数据库"
(5)Set rs = conn.Execute(sql) "执行SQL语句"
(6)If Not rs.EOF = True Then  "当前的记录位于Connection对象的最后一个记录之前"
(7)Session("Name") =  rs("UserName")  "将UserName的属性赋给Name的Session自定义变量"
(8)Session("pwd") =  rs("PassWord")  "将PassWord的属性赋给pwd的Session自定义变量"
(9)Response.Redirect("Manage.asp")了  "利用Response对象的Redirect方法重定向"Manage.asp"
(10)Else
(11)Response.Redirect "Loginsb.asp?msg=您输入了错误的帐号或口令,请再次输入!"
(12)End If
(13)end if
%>
知道原理之后 我们就可以修补了
把(1)(2)的内容修改成
pwd = replace(request.form("pwd"),"'","") //意思就是把'替换为空
name = replace(request.form("name"),"'","") //同上
为了保险后台最好设置登陆用户 登陆密码 还有验证码

Tags: 程序

发布: 老漂 分类: 网站|站长 评论: 0 浏览: 88
留言列表
发表留言
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。