安全中国首页 > 文章中心 > 技巧知识
 
安全中国网友投稿专用上传FTP空间:
Ftp服务器:www.anqn.com
Ftp端口:21
用户名:anqn
密 码:anqn.com
 

对一小BUG的分析、假想和成功利用(图)

更新时间:2008-7-7 2:32:50
责任编辑:阿loosen
热 点:
以我的观点来看,这应该是一个Bug(虽然利用不了,但是值得注意),这个小Bug是我在测试SystemDev新闻系统时发现的,因为无多大用处而又是假想主义,所以就和《SystemDev新闻系统漏洞分析》这篇文章分开写了(高手请略过)。

  小Bug分析

  我们先来看后台验证文件session.asp的部分代码。

  AdminUID=session("AdminUID")

  AdminPWD=session("AdminPWD")

  set rs=server.CreateObject ("ADODB.RecordSet")

  rs.Source="select id from Admin where AdminUID='" & AdminUID & "' and AdminPWD='" & AdminPWD & "'"

  rs.Open rs.Source,conn,1,1

  这段代码以会话验证AdminUID和AdminPWD,并存入各自对应的变量中,然后这两个变量都参与了SQL查询(其中AdminUID和AdminPWD是通过AdminUID=trim(Request.Form("AdminUID"))和AdminPWD=trim(Request.Form("AdminPWD"))得到的)。而大部分文件都include了session.asp文件,从这里来看,程序貌似很安全。

  接下来我们看这两个文件:ChangPassword1.asp和ChangPassword2_submit.asp,其功能是管理员用来更改密码的。这两个文件都没有include session.asp文件,而且ChangPassword1.asp没有任何权限判断语句(这应该是比较危险的了)。当然,这个文件不会有什么威胁。在ChangPassword2_submit.asp中我们可以看到这样一句代码:“UserName=session("AdminUID")”,大家看到这一句可能会觉得没戏了,其实不然,这句代码的作用是将AdminUID会话保存在变量UserName中。如果按照一般的思路,接下来的代码可能会这么写:

        If UserName="" then

  Response.Write "登录超时,请重新登录!"

  Response.End

  但是作者却没有做出会话的判断,而是直接写出了下面的代码。

  

        OldPassword=trim(Request.Form("OldPassword"))

  NewPassword=trim(Request.Form("NewPassword"))

  NewPassword2=trim(Request.Form("NewPassword2"))

  ……省略……

  set rs=server.CreateObject ("ADODB.RecordSet")

  rs.Source="select id from Admin where AdminPWD='" & OldPassword & "'"

  rs.Open rs.Source,conn,1,1

  if not rs.EOF then

  sql="update Admin set AdminPWD='" & NewPassword & "' where AdminUID='" & UserName & "'"

  conn.execute(sql)

  session("AdminPWD")=NewPassword

  它直接接受了第一个文件传过来的数据,然后存储到三个密码变量中,再执行SQL查询。在SQL查询中,“sql="update Admin set AdminPWD='" & NewPassword & "' where AdminUID='" & UserName & "'" ”将保存会话的值的变量参与了UserName查询。不知道是作者侥幸还是真的想这么判断,这里导致的结果是,我们不能直接更改管理员的密码,为什么呢?因为UserName里保存的是会话!而在服务器上并不保存我们的会话,所以即便我们进行修改的话,也不可能达到修改管理员密码的目的。从代码可以看出,我们可以在修改密码处进行注入,但是不会威胁到系统。这里先介绍一下,因为下面要用到,ChangPassword1.asp的界面如图1所示。

              

                                                                                                    图一

  虽然服务器没有保存我们的Session,但是大家看下面的代码:

       set rs=server.CreateObject ("ADODB.RecordSet")

  rs.Source="select id from Admin where AdminPWD='" & OldPassword & "'"

  rs.Open rs.Source,conn,1,1

  它仍然对旧密码进行了查询。而在这里,我们看到了OldPassword变量保存的是Request.Form("OldPassword")的值,也就是说用request.form方法从客户端获取数据oldpassword实现SQL查询,而且只过滤了尾部的空格,所以这里仍然可以进行注入。不信?那下面就验证一下吧。

随便输入123456(我自己测试的环境,管理员密码是13),然后再随便输入新密码,提交一下,返回如图2所示。怎么样?虽说在update数据的时候不成功,但是在输入旧密码的时候它仍然要进行查询。再构造另一条语句:“huahua' or '1'='1”,把它放在旧密码处,然后新密码随便输,提交一下,返回如图3所示。为什么会这样?第一,我们在文本框进行了注入,注入后的语句是:“select id from Admin where AdminPWD='huahua' or '1'='1'”,这是明显成立的语句,所以就成功绕过去了;第二个原因是这套程序在update失败的时候,并没有做出处理(对旧密码查询处的查询失败会报错),所以直接说密码修改成功了。虽然返回信息说成功了,但事实上我们并没有成功地修改管理员的密码,原因在上面我已经解释过了。

                    

  假 想

  既然利用不了,那么我们自己就可以这样设想,为自己设一个难题,再让自己去突破。我自己的想法是将会话联系到另外一个地方,如果UserName保存的不是会话,而是Request.Form()传来的数据呢?此时能否利用?又该如何利用呢?

  要这么做,我们先得修改一下测试环境。在ChangPassword1.asp加入如下代码,则ChangPassword1.asp的界面就会变成如图4所示的效果。

            

<td width="87">管理员</td>

<td width="349"><input type="text" name="username" size="20"></td>

</tr>

  接下来再看一下原密码,以便和修改之后的密码做比较,如图5所示。然后在ChangPassword2_submit.asp文件处做一下修改,把UserName=session("AdminUID")改成username=request.form("username")即可。打开第一个文件进行修改密码,在管理员处输入“huahua' or '1'='1”,并在第二个地方也输入“huahua' or '1'='1”,新密码处随便填,然后提交,系统返回密码修改成功。此时我们再看一下数据库的内容,如图6所示,两个管理员的密码都被改成了123!

           

  为什么我们提交的用户名(huahua)和管理员的用户名(sa与SystemDev)不同,却仍然能够修改成功呢?而且提交一个用户的信息却把两个默认用户的密码都修改了?呵呵,其实前面我已经解释过了,不懂的朋友再仔细看看,然后自己分析一下,就算是一个作业吧!

  总之,在入侵的时候,只要我们多一份想象,多一份思路,多一份突破,多一份进步,便会多一份成功的!

 
相关文章
一日一文章
 
一日一软件
一日一动画