一次格盘钓鱼网站之后引发的深思

2016-01-20 17:37:49 12 4249
网站早已经被我们拿下来了,弱点是ftp匿名竟然有读写权限,所以拿shell的过程很简单。后面提权也是比较顺利,直接exp秒了,都没什么亮点。



主要讲的是,我在拿shell的时候遇到问题和思考。刚开始,可以ftp下载源码,我也没有去拿shell了,shell是叫我朋友拿的,我拿到代码之后,看见了一个上传点,于是我就开始审计了,最后是不能getshell的,但是我突然想起了很古老的双文件双上传,那时候不懂原理,借着今天这次机会,拿过来分析一下,这里说的是我自己的理解,都是大白话,写技术类文采不好,求不打。

还是先看钓鱼网站的源码吧,asp,看起来有点费眼睛,我也懒得调背景颜色了。







指向的是upfile_link.asp,直接看代码。
<%@language=vbscript codepage=936 %>
<!--#include file="upfile_class.asp"-->
<%
const upload_type=0   '上传方法:0=无惧无组件上传类,1=FSO上传 2=lyfupload,3=aspupload,4=chinaaspupload
const UpFileType="apk|jpg"
const MaxFileSize=20

dim upload,oFile,formName,SavePath,filename,fileExt,oFileSize
dim EnableUpload
dim arrUpFileType
dim ranNum
dim msg,FoundErr
dim UrlID
dim filesname


filesname="10086.apk"
msg=""
FoundErr=false
EnableUpload=false
SavePath="ftp"
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<style type="text/css">
<!--
BODY{
BACKGROUND-COLOR: #FFFFFF;
font-size:9pt
}
.tx1 { height: 20px;font-size: 9pt; border: 1px solid; border-color: #000000; color: #0000FF}
-->
</style>
</head>
<body leftmargin="2" topmargin="5" marginwidth="0" marginheight="0" >
<%

                select case upload_type
                        case 0
                                call upload_0()  '使用化境无组件上传类
                        case else
                                'response.write "本系统未开放插件功能"
                                'response.end
                end select

%>
</body>
</html>
<%
sub upload_0()    '使用化境无组件上传类
        set upload=new upfile_class ''建立上传对象
        upload.GetData(MaxFileSize*1024*1024)   '取得上传数据,限制最大上传100M
        if upload.err  0 then  '如果出错
                select case upload.err
                        case 1
                                response.write "请先选择你要上传的文件!"
                        case 2
                                response.write "你上传的文件总大小超出了最大限制("&MaxFileSize&"M)"
                end select
                response.end
        end if

        
        if right(SavePath,1)"/" then SavePath=SavePath&"/" '在目录后加(/)
               
        for each formName in upload.file '列出所有上传了的文件
                set ofile=upload.file(formName)  '生成一个文件对象
                oFileSize=ofile.filesize
                fname=ofile.FileName
               
                if ucase(filesname)ucase(fname) then
                msg="文件名错误,上传文件名只能是" & filesname & "!"
                FoundErr=true
                end if
               
'                response.Write(filename)
'                response.End()
                if oFileSize100 then
                        msg="请先选择你要上传的文件!"
                        FoundErr=True
                else

                    if oFileSize(MaxFileSize*1024*1024) then
                  msg="文件大小超过了限制,最大只能上传" & MaxFileSize & " M的文件!"
                         FoundErr=true
                    end if
        
                end if

                fileExt=lcase(ofile.FileExt)
                arrUpFileType=split(UpFileType,"|")
                for i=0 to ubound(arrUpFileType)
                        if fileEXT=trim(arrUpFileType(i)) then
                                EnableUpload=true
                                exit for
                        end if
                next
                if fileEXT="asp" or fileEXT="asa" or fileEXT="aspx" or fileEXT="jsp" or fileEXT="php" then
                        EnableUpload=false
                end if
                if EnableUpload=false then
                        msg="这种文件类型不允许上传!\n\n只允许上传这几种文件类型:" & UpFileType
                        FoundErr=true
                end if
               
                if FileExits(SavePath&fname) then DeleteFile (SavePath&fname)
               
                response.write("FoundErr:                       ")
                response.write(FoundErr)
                response.write("EnableUpload:                 ")
                response.write(EnableUpload)
                strJS="SCRIPT language=javascript" & vbcrlf
                if FoundErrtrue then
                        randomize
                        ranNum=int(900*rnd)+100
                        filename=SavePath&fname

                        ofile.SaveToFile Server.mappath(FileName)   '保存文件

                        'response.write "文件上传成功!文件大小为:" & cstr(round(oFileSize/1024)) & "K"

                                        strJS=strJS & "parent.document.getElementById('TPUrl').value='" & fileName & "';" & vbcrlf
                                        strJS=strJS & "alert('文件上传成功!文件大小为:" & cstr(round(oFileSize/1024)) & "K " & "');top.location.href='admin/order.asp';" & vbcrlf

                else
                        strJS=strJS & "alert('" & msg & "');" & vbcrlf
                          strJS=strJS & "history.go(-1);" & vbcrlf
                end if
                strJS=strJS & "/script" & vbcrlf
                response.write strJS
               
                set file=nothing
        next
        set upload=nothing
end sub
%>
(ps:代码还是贴出来吧。但是分析的话,只要记住几个关键的变量就行)



中间什么初始化变量之类和其他杂七杂八的代码,我就不看了,直接跳到关键部分
for each formName in upload.file '列出所有上传了的文件
                set ofile=upload.file(formName)  '生成一个文件对象
                oFileSize=ofile.filesize
                fname=ofile.FileName
               
                if ucase(filesname)ucase(fname) then
                msg="文件名错误,上传文件名只能是" & filesname & "!"
                FoundErr=true
                end if
               
'                response.Write(filename)
'                response.End()
                if oFileSize100 then
                        msg="请先选择你要上传的文件!"
                        FoundErr=True
                else

                    if oFileSize(MaxFileSize*1024*1024) then
                  msg="文件大小超过了限制,最大只能上传" & MaxFileSize & " M的文件!"
                         FoundErr=true
                    end if
        
                end if

                fileExt=lcase(ofile.FileExt)
                arrUpFileType=split(UpFileType,"|")
                for i=0 to ubound(arrUpFileType)
                        if fileEXT=trim(arrUpFileType(i)) then
                                EnableUpload=true
                                exit for
                        end if
                next
                if fileEXT="asp" or fileEXT="asa" or fileEXT="aspx" or fileEXT="jsp" or fileEXT="php" then
                        EnableUpload=false
                end if
                if EnableUpload=false then
                        msg="这种文件类型不允许上传!\n\n只允许上传这几种文件类型:" & UpFileType
                        FoundErr=true
                end if
               
                if FileExits(SavePath&fname) then DeleteFile (SavePath&fname)
               
                response.write("FoundErr:                       ")
                response.write(FoundErr)
                response.write("EnableUpload:                 ")
                response.write(EnableUpload)
                strJS="SCRIPT language=javascript" & vbcrlf
                if FoundErrtrue then
                        randomize
                        ranNum=int(900*rnd)+100
                        filename=SavePath&fname

                        ofile.SaveToFile Server.mappath(FileName)   '保存文件

                        'response.write "文件上传成功!文件大小为:" & cstr(round(oFileSize/1024)) & "K"

                                        strJS=strJS & "parent.document.getElementById('TPUrl').value='" & fileName & "';" & vbcrlf
                                        strJS=strJS & "alert('文件上传成功!文件大小为:" & cstr(round(oFileSize/1024)) & "K " & "');top.location.href='admin/order.asp';" & vbcrlf

                else
                        strJS=strJS & "alert('" & msg & "');" & vbcrlf
                          strJS=strJS & "history.go(-1);" & vbcrlf
                end if
                strJS=strJS & "/script" & vbcrlf
                response.write strJS
               
                set file=nothing
        next
        set upload=nothing
end sub
开头是一个for循环遍历所有的上传变量,最后检测能够上传成功与否的条件是FoundErr时候为false还是true。(ps:当然你也可以理解FoundErr为中文意思,就是发现出错,的意思是大于或者小于,换言之,在asp里面表示不等于,也就如果没有发现上传出错的时候,就能够上传)



相当安全,无懈可击啊。我们简单分析下代码流程,(ps:我写这么清楚,这么详细,如果你还看不懂,那么你真可以去死了)。先得到文件名,和前面的变量filesname比较是否相等,也就是你的文件名必须是10086.apk(ps:坑吧,我会告诉你10086.apk就是那个钓鱼网站的app,当然app我也下了,暂时还未分析弱点,等有空一起写上来吧)。如果不是的话,那么FoundErr就为true,那么最后的逻辑就进不去了,也就是上传失败咯,后面还检查后缀名是否含有asp,php等之类的,如果有的话EnableUpload为false,当EnableUpload为false的时候,FoundErr就赋值为true了,写这么多就是想告诉你,代码简直无懈可击,反正我是绕不过。但是我感觉好像很熟悉的感觉,于是我下载了双文件上传的代码,果然代码是差不多的,我说看着怎么这么眼熟。下面是那个经典的双文件上传漏洞代码,前面都差不多,就是少了一句前面的检测是否为10086.apk的操作:
for each formName in upload.file '列出所有上传了的文件
                set ofile=upload.file(formName)  '生成一个文件对象
                oFileSize=ofile.filesize
                fname=ofile.FileName
                if oFileSize100 then
                        msg="请先选择你要上传的文件!"
                        FoundErr=True
                else

                    if oFileSize(MaxFileSize*1024*1024) then
                  msg="文件大小超过了限制,最大只能上传" & MaxFileSize & " M的文件!"
                         FoundErr=true
                    end if
        
                end if

                fileExt=lcase(ofile.FileExt)
                arrUpFileType=split(UpFileType,"|")
                for i=0 to ubound(arrUpFileType)
                        if fileEXT=trim(arrUpFileType(i)) then
                                EnableUpload=true
                                exit for
                        end if
                next
                if fileEXT="asp" or fileEXT="asa" or fileEXT="aspx" or fileEXT="jsp" or fileEXT="php" then
                        EnableUpload=false
                end if
                if EnableUpload=false then
                        msg="这种文件类型不允许上传!\n\n只允许上传这几种文件类型:" & UpFileType
                        FoundErr=true
                end if
               
                if FileExits(SavePath&fname) then DeleteFile (SavePath&fname)
               
                response.write("FoundErr:                       ")
                response.write(FoundErr)
                response.write("EnableUpload:                 ")
                response.write(EnableUpload)
                strJS="SCRIPT language=javascript" & vbcrlf
                if FoundErrtrue then
                        randomize
                        ranNum=int(900*rnd)+100
                        filename=SavePath&fname

                        ofile.SaveToFile Server.mappath(FileName)   '保存文件

                        'response.write "文件上传成功!文件大小为:" & cstr(round(oFileSize/1024)) & "K"

                                        strJS=strJS & "parent.document.getElementById('TPUrl').value='" & fileName & "';" & vbcrlf
                                        strJS=strJS & "alert('文件上传成功!文件大小为:" & cstr(round(oFileSize/1024)) & "K " & "');top.location.href='admin/order.asp';" & vbcrlf

                else
                        strJS=strJS & "alert('" & msg & "');" & vbcrlf
                          strJS=strJS & "history.go(-1);" & vbcrlf
                end if
                strJS=strJS & "/script" & vbcrlf
                response.write strJS
               
                set file=nothing
        next
        set upload=nothing
end sub
上传单个文件,依旧是十分安全的,但是当上传两个文件的时候,噩梦开始了。可以看到这里是黑名单规则,假设我们上传的是12222.jpg和xxxxxx.cer。当第一个文件上传的时候,他的size不小于100,所以FoundErr依旧为false,然后他的size没有超过MaxFileSize*1024*1024,所以依旧是false,接下来把UpFileType分割成数组,里面的值也就是apk和jpg。然后在一个for循环啪啪啪的检测后缀,哲理后缀是jpg,当然满足条件,于是乎EnableUpload的值为true。
for i=0 to ubound(arrUpFileType)
                        if fileEXT=trim(arrUpFileType(i)) then
                                EnableUpload=true
                                exit for
                        end if
                Next
然后,他又不是这些黑名单里面的值,所以EnableUpload依旧是true
if fileEXT="asp" or fileEXT="asa" or fileEXT="aspx" or fileEXT="jsp" or fileEXT="php" then
                        EnableUpload=false
                end if
因为EnableUpload等于true,所以FoundErr的值还是false,最后就上传成功了。
                if EnableUpload=false then
                        msg="这种文件类型不允许上传!\n\n只允许上传这几种文件类型:" & UpFileType
                        FoundErr=true
                end if
注意,到目前为止,FoundErr的值为false,EnableUpload的值为true,当我们上传第二个cer文件呢?很明显不满足后缀是jpg和apk,,不满足条件,于是保持原来的值,但是问题是经过上一个文件上传,我们的EnableUpload是true。后面检测黑名单的话,也是不满足条件的,继续保持原值。一直到最后一步,很显然的逻辑EnableUpload还是为true,那么FoundErr最后出来的值还是false,所以cer文件也就乖乖的上传成功了。够累的,分析完了。


总结:学东西不要浅尝辄止,要继续深入下去,这样才能真正学到东西。2016年注定是难熬和苦难的一年,(ps:老夫要考研),祝大家红红火火吧,最后,祝我考研顺利吧。

关于作者

评论12次

要评论?请先  登录  或  注册