Question to say "I can!"

淺析上傳漏洞的形成

2015-02-04

偶介紹一種漏洞--上傳漏洞,這是一種比注入更有殺傷力的漏洞。通過注入所得到的往往是數據庫中

的一些敏感信息,如管理員名稱、密碼等等(注:此處注入指的是MDB數據庫),但上傳漏洞就不同了,它可

以把ASP、JSP、CGI、PHP等格式的木馬上傳至網站目錄內,所得到的權限最低也是WEBSHELL,如果碰到的是安

全意識不強的管理員,呵呵!那就可以客串一把管理員了!心動了吧!OK!那就LET'S GO!
對于上傳漏洞的查找,仍是從源文件入手,目標有兩個,一個是FilePath(文件路徑),另一個則是

FileName(文件名稱)。

一、FilePath
說到FilePath,有些朋友可能感到陌生,但要提到動網6.0的上傳漏洞,大家一定不陌生吧!其上傳漏

洞就是由于FILEPath過濾不嚴引起的。雖然動網已不存在此漏洞了,但采用此上傳源碼的程序還是大有人在的

,比如我手頭這款“萬豪下載程序”,其ADS(廣告)版塊中的Upfile.asp(上傳),就有Filepath過濾不嚴

的漏洞,(刺猬2005作品)來分析一下其部分源碼:
以下是引用片段:
<%
dim upload,file,formName,formPath,iCount,filename,fileExt ’//定義上傳變量
set upload=new upload_5xSoft ’//建立上傳對象JM的測試代碼
formPath=upload.form("filepath") ’//第一步、獲取文件路徑,此處是關鍵。
if right(formPath,1)<>"/" then formPath=formPath&"/"
for each formName in upload.file ’//用For讀取上傳文件
set file=upload.file(formName) ’//生成一個文件對象jmdcw
…………………… ’//省略部分代碼
fileExt=lcase(right(file.filename,4)) ’//從文件名中截取后4位,并轉換為小寫字符。
if fileEXT<>".gif" and fileEXT<>".jpg" and fileEXT<>".zip" and fileEXT<>".rar" and

fileEXT<>".swf"then ’//文件擴展名判斷
response.write "<font size=2>文件格式不正確 [ <a href=# onclick=history.go(-1)>重新上傳</a> ]

</font>"
response.end
end if
randomize
ranNum=int(90000*rnd)+10000
filename=formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum&fileExt

’//第二步、filename由提交的文件路徑+年月日的隨機文件名+轉換后的擴展名組成
if file.FileSize>0 then
file.SaveAs Server.mappath(FileName)???? ’//保存文件jmdcw
end if
set file=nothing
next
%>
在這段源碼中,要關鍵的就這兩句:
以下是引用片段:
1、formPath=upload.form("filepath")
2、filename=formPath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)

&ranNum&fileExt

廣告插播。變量與常量:所謂變量就是指在程序的運行過程中隨時可以發生變化的值;而常量則恰恰相

反,指的是在程序的運行過程中始終保持不變的值。
下面來看一下漏洞是如何形成的。在第一句代碼中,從變量filepath中獲取文件的保存路徑,然后在第

二句中,用路徑變量formPath加隨機生成的數字及經過判斷的擴展名合成為一個新的變量,這個變量Filename

就是上傳文件保存的路徑及名稱。這樣說有些籠統,下面舉例說明。

比如選擇“111.jpg”文件上傳,在上傳過程中,隨文件一起上傳的還有一個FilePath變量,假設其值

為“image”,當這些值傳到upfile.asp中,filename就變成了:“image/200512190321944973.jpg”,上傳

成功后,該111.jpg就被保存到image文件夾內,文件名字也被改成了:“200512190321944973.jpg”。這段流

程,看起來無懈可擊,但還是被牛人研究出了突破方法,什么方法呢?很簡單,突破點就在變量身上,如果將

其FilePath值改為“image/aa.asp□”,其后的“□”表示二進制的00(空的意思),這樣,該變量提交入

upfile.asp后,Filename值就變成了“image/aa.asp□/200512190321944974.jpg”,服務器在讀取這段變量

時,因為“□”是二進制的00,認為該變量語句已經結束了,于是“□”后面的字符也就被忽略掉了,這樣一

來,Filename就成了:“image/aa.asp”,程序再用file.SaveAs進行保存的話,這個文件就保存成了aa.asp

文件,瞧!漏洞出現了。

對于這個漏洞的利用,可以使用桂林老兵的上傳工具,也可以采取用WinSock抓包,然后用記事本保存

提交數據并增加、修改相關內容,再用WinHex修改空格為二進制,最后用NC提交的方法。

二、FileName
介紹過FilePath(上傳路徑)過濾不嚴的漏洞,再來看一看FileName(上傳文件名)過濾不嚴造成的漏

洞,上傳文件名過濾不嚴的形式是多種多樣的,偶這里介紹兩種:
1、動易文章
2005.10期中的《再現昔日漏洞——沁竹音樂程序的疏忽》,所涉及的上傳漏洞就是動易的上傳漏洞,

下面以此為例,來看一下其上傳文件Upfile_Article.asp中的部分源碼:
以下是引用片段:
<%
Const UpFileType="rar|gif|jpg|bmp|swf|mid|mp3" ’//允許的上傳文件類型jmdcw
Const SaveUpFilesPath="../../UploadFiles"???????? ’//存放上傳文件的目錄,注:以上兩個常量均在

config.asp文件內定義’刺猬測試代碼
dim upload,oFile,formName,SavePath,filename,fileExt //變量定義
……………………
FoundErr=false????? ’//此為是否允許上傳的變量,初始化為假,表示可以上傳。
EnableUpload=false???? ’//此為上傳文件擴展名是否合法的變量,初始化為假,表示的是不合法。
SavePath = SaveUpFilesPath???? ’//存放上傳文件的目錄
……………………
sub upload_0()????? ’//使用化境無組件上傳
set upload=new upfile_class ’//建立上傳對象
……………………
for each formName in upload.file ’//用For循環讀取上傳的文件。 jmdcw
set ofile=upload.file(formName) ’//生成一個文件對象
……………………
fileExt=lcase(ofile.FileExt) ’//將擴展名轉換為小寫字符
arrUpFileType=split(UpFileType,"|") ’//讀取后臺定義的允許的上傳擴展名
for i=0 to ubound(arrUpFileType)???? ’//第一關,用FOR循環讀取arrUpFileType數組。
if fileEXT=trim(arrUpFileType(i)) then???? ’//如果fileEXT是允許上傳的擴展名
EnableUpload=true???? ’//EnableUpload為真,表示該文件合法。
exit for
end if
next
if fileEXT="asp" or fileEXT="asa" or fileEXT="aspx" then ’// 第二關,驗證fileEXT是否為asp、asa

、aspx擴展名。
EnableUpload=false???? ’//如果屬于這三項之一,那么EnableUpload就定義為假,上傳文件擴展名不合法

。jm
end if
if EnableUpload=false then ’// 第三關,驗證關。如果傳遞到此的EnableUpload變量為假,則說明上傳文

件擴展名不合法。
msg="這種文件類型不允許上傳!\n\n只允許上傳這幾種文件類型:" & UpFileType
FoundErr=true ’//注意:因為文件名不合法,就更改了FoundErr值,由初始的false改為true。
end if
strJS="<SCRIPT language=javascript>" & vbcrlf
if FoundErr<>true then???? ’//第四關,上傳關。如果FoundErr不等于true才可以上傳。
randomize
ranNum=int(900*rnd)+100
filename=SavePath&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)

&ranNum&"."&fileExt???? ’//定義filename,其值為固定的路徑名+年月日及隨機值生成的名稱+傳遞過來的

fileExt擴展名。
ofile.SaveToFile Server.mappath(FileName)???? ’//保存文件 cw’s
msg="上傳文件成功!"
……………………
next
set upload=nothing
end sub
%>
在這段源碼中,用到了兩個FOR循環、兩個邏輯變量,第一個FOR循環“for each formName in

upload.file”用于取得所有上傳的文件名;第二個FOR循環“for i=0 to ubound(arrUpFileType) ”用于檢

測文件擴展名。而兩個邏輯變量是EnableUpload和FoundErr,EnableUpload用于表示文件擴展名的合法性,

True表示合法;而FoundErr則用于表示文件是否可以上傳,False表示可以上傳,很奇怪?用的是False!如果

我們上傳的是一個文件,那此段代碼是無懈可擊的,但要上傳兩個呢?因為化境無組件上傳可以上傳多個文件

,OK!來看一下上傳多個文件的流程:
首先,構造一個有兩個上傳框的本地HTM文件,HTM代碼如下:
以下是引用片段:
<form action="http://www.jmdcw.com/admin/Article/Upfile_AdPic.asp" method="post" name="form1">
<input name="FileName1" type="FILE" size="40">
<input name="FileName" type="FILE" size="40">
<input type="submit" name="Submit" value="上傳" >
</form>

運行這個HTM,在第一個框內選擇一個jpg圖片,文件名為“111.jpg”,在第二個框內選擇一個Cer文件

,文件名為“222.cer”,點“上傳”把這兩個文件提交給程序。接下來到Upfile_AdPic.asp中觀察這兩個文

件的上傳流程(注意其中邏輯變量的變化)。
1、在進入第一個FOR(讀取文件名)之前,程序先將變量FoundErr定義為false、EnableUpload定義為

false,然后讀取文件名,先驗證第一個文件111.jpg,在驗證的第一關中,jpg屬于允許上傳的類型,變量

EnableUpload=true。
2、接著到第二關,檢驗是否屬于三種禁傳類型,因為不屬于,變量EnableUpload仍為true。
3、再到第三關卡,如果EnableUpload=false,那么FoundErr=true,而前面傳遞來的

EnableUpload=true,那FoundErr仍為進入第一個FOR循環之前的false。
4、最后進入第四關,此關的驗證是:如果FoundErr<>true就可以通過,看一下從第三關傳遞過來的

FoundErr的值,是false,可以上傳。這里請注意,在111.jpg上傳后,EnableUpload的值保持為true,

FoundErr的值是false。
5、接著程序讀取第二個文件222.cer,進入第一關驗證是否為允許上傳類型,如果cer屬于此范圍就給

EnableUpload定義為true,而cer不屬于,所以就保持原值,EnableUpload的原值是什么?看一下111.jpg上傳

后的變量值:“EnableUpload的值保持為true”,那么此時cer文件的EnableUpload值就是true了。
6、再到第二關,cer同樣不屬于此限制范圍,又跳過IF語句,再看EnableUpload的值,仍保持為true。
7、又到第三關了,因為EnableUpload=true,又跳過了此關驗證。直接進入第四關,這時回頭看一下

FoundErr的值,自cer進行上傳驗證開始,一直未出現FoundErr,FoundErr的值是什么?呵呵,它還是111.jpg

上傳后的值false,而第四關的驗證就是只要FoundErr不是true就可以上傳,所以,這個cer文件也就通過了層

層關卡,進入了服務器。
除了cer格式的,還可以上傳asp□(□在這里表示空格,以下同)、asp.格式的文件,方法很簡單,就

是把上傳框中的asp名稱加入空格或小數點,因為是asp□、asp.格式,其繞過方式和cer是一樣的,而上傳到

服務器中的asp□或asp.的擴展名,因為Windows文件命名原則,會去除后面的空格和小數點,保存的就是asp

格式了。

2、動感商務2005
說過了動易的上傳漏洞,再來介紹動感商務2005的上傳漏洞,今天真是太巧了,動網、動易、動感,全

是帶動的,哈哈!動易是由于上傳多個文件引起的漏洞,而動感則是因為文件名過濾不嚴出現上傳漏洞。下面

是動感2005上傳upfile.asp中的部分源碼:
以下是引用片段:
<%
Private Sub SaveFile_0() ’//無組件上傳
……………………
Set File = UploadObj.File(FormName) ’//取得上傳文件名 cw’s files
FileExt = FixName(File.FileExt) ’//第一步、用FixName函數過濾上傳文件的擴展名
If CheckFileExt(FileExt) = False then ’//第二步、用CheckFileExt檢查過濾后的文件擴展名
ErrCodes = 5
EXIT SUB ’//退出上傳
End If
FileName = FormatName(FileExt) ’//符合條件的話,就用FormatName函數按日期生成文件名
……………………
If File.FileSize>0 Then
File.SaveToFile Server.Mappath(FilePath & FileName) ’//保存的文件路徑及名稱是Filepath+FileName
……………………
End Sub
%>
下面再來看一下上傳所涉及到的一些參數。
A、FixName()函數:
以下是引用片段:
Private Function FixName(Byval UpFileExt) ’//第一步的過濾函數,過濾特殊擴展名。
If IsEmpty(UpFileExt) Then Exit Function ’//如擴展名為空就退出交互
FixName = Lcase(UpFileExt)???????? ’//將擴展名轉換為小寫字符。
FixName = Replace(FixName,Chr(0),"")???? ’//將二進制的00空字符過濾為空
FixName = Replace(FixName,".","")????? ’//將單引號過濾為空,下同。 jmdcw
FixName = Replace(FixName,"’","")
FixName = Replace(FixName,"asp","")
FixName = Replace(FixName,"asa","")
FixName = Replace(FixName,"aspx","")
FixName = Replace(FixName,"cer","")
FixName = Replace(FixName,"cdx","")
FixName = Replace(FixName,"htr","")
FixName = Replace(FixName,"shtml","")
End Function

從中,我們可以看出,應用程序asp.dll映射的類型全部過濾了,除此之外,還有小數點、單引號也被

過濾,甚至連Chr(0)都過濾了,Chr(0)是什么?它就是16進制的0x00,表示為二進制是00000000,也就是前面

在FilePath上傳漏洞中大顯神通的空字符。
B、CheckFileExt()函數:
以下是引用片段:
Private Function CheckFileExt(FileExt) ’//第二步的判斷函數,判斷文件類型是否合乎要求
Dim Forumupload,i
CheckFileExt=False???? ’//定義CheckFileExt的初始值為假,
If FileExt="" or IsEmpty(FileExt) Then ’//第一次、為空則退出
CheckFileExt = False
Exit Function
End If
If FileExt="asp" or FileExt="asa" or FileExt="aspx" or FileExt="shtml" Then???? ’//第二次、如果

屬于這四種類型也退出交互
CheckFileExt = False
Exit Function
End If
Forumupload = Split(InceptFile,",")???? ’//第三次、從InceptFile中提取后臺的上傳擴展名
For i = 0 To ubound(Forumupload) ’//用For循環檢驗
If FileExt = Trim(Forumupload(i)) Then ’//如果和后臺中的任一上傳擴展名相符,則CheckFileExt =

True。
CheckFileExt = True
Exit Function
Else
CheckFileExt = False
End If
Next
End Function
這個函數對經過FixName()函數過濾后的擴展名再次判斷,其中有三次檢查,第一次是判斷傳遞而來的

擴展名是否為空,為空則退出上傳,第二次是判斷擴展名是否屬于asp、asa等四種限傳類型,屬于也退出上傳

,第三次就是用該擴展名同后臺內自定義的上傳擴展名進行對比,符合就允許上傳。
C、FilePath值:
其所用到的filepath在upload.asp中,其值如下:
以下是引用片段:
if info_name="bbs" then
FilePath = "/bbs/upload/"
else
FilePath = "/uploadpic/"
end if
FilePath是一個常量,從這條路找漏洞是行不通的了。
OK!下面上傳一個文件來看其驗證流程,比如上傳的文件名為“111.cer”,在用“FileExt =

FixName(File.FileExt)”過濾擴展名時,因為cer屬于fixName()函數的過濾范圍,所以擴展名cer就成了空,

當把這個空的擴展名傳遞給CheckFileExt(),在其進行到“If FileExt="" or IsEmpty(FileExt)”語句時,

就會因為FileExt為空而退出交互,返回格式不正確,拒絕上傳。
如何突破呢?其突破點就在FixName()函數中,上面我們也看到,在上傳時cer會被過濾為空,但如果我

們把上傳文件擴展名改為ccerer,同時,在后臺的自定義上傳類型中增加“ccerer”、“cer”,這樣,擴展

名為ccerer的文件在經過第一步FixName()的過濾后,ccerer就變成了cer(中間的cer字符被過濾為空),傳

遞此值到CheckFileExt()函數中,通過其第一次不空的關卡,再通過第二次限制類型的關卡,最后到對比后臺

上傳類型關卡,因為在前面我們已添加了“ccerer”、“cer”兩種類型,那么也就通過CheckFileExt()第三

次的判斷,CheckFileExt = True,也就把這個擴展名ccerer的文件上傳到服務器中了,并且上傳后的擴展名

是cer。
有的朋友可能會問,如果上傳擴展名為aaspsp□或aaspsp.格式的文件,在經過FixName()函數的過濾,

不就變成了asp□或asp.了,而這兩種格式也不在限制的范圍,只要在后臺中加上這幾種類型,不就可以把上

傳的文件保存為asp格式了?其實當初我也是這個想法,但經過仔細的研究分析,發現此路不通,為什么?先

說小數點,在FixName()中,有這么一句,FixName = Replace(FixName,".",""),將小數點過濾為空,瞧!小

數點的路斷了。再來看空格,雖然FixName()中沒有過濾空格,但在CheckFileExt()讀取后臺上傳類型時有這

么一句:“If FileExt = Trim(Forumupload(i)) Then ”,其中有個Trim(),Trim的作用是刪除字符串開始

和尾部的空格。雖然在后臺能寫入了asp□類型,但在讀取時,卻會被Trim()過濾成asp,而aaspsp□通過層層

關卡到了此處,已變成了asp□,asp□<>asp,證件不符!Sorry,拒絕進入!

總而言之,上傳漏洞是比較吸引眼球的。偶用上面三個例子對上傳漏洞管中窺豹了一番,希望對各位朋

友有所幫助。呵呵!相信自已,說不定下一個發現新的上傳漏洞的牛人就是你!

作者:admin | Categories:優化維護 | Tags:

發表評論

電子郵件地址不會被公開。 必填項已用*標注

*

澳洲f1赛车b盘开奖套路 管家婆平特一肖玄机图 亿海智投 北京十一选五怎么玩 黑龙江省福彩22选五走势图 福建体彩31迭7走势图 腾讯分分彩如何快速刷流水 山西快乐十分软件下载 浙江体彩6 1走势图 权重股蓝筹股 四川金七乐app官方 吉林十一选五前三直走势 浙江6 1什么时候开 贵州快3app 上证指数股吧讨论区 浙江快乐十二遗漏数据 贵州十一选五胆拖投注法