通達OA 漏洞分析

漏洞通報信息:

https://mp.weixin.qq.com/s/_bpg8buT92dzRuGdr2ZrRg

https://mp.weixin.qq.com/s/s1yqJNOsCk-uVyCtg6SG7A

 

OA-2017非官網:http://www.downxia.com/downinfo/202980.html

最新版v11下載地址:http://www.tongda2000.com/download/2019.php?F=baidu_natural&K=

補丁包:http://cdndown.tongda2000.com/oasp/2019/2020_A1.rar

 

 

下載補丁包查看,發現新版v11的補丁有點多啊,又看了一下2017版本的,發現只修改了一個ispirit/im/upload.php。於是選擇先分析OA2017作爲切入點,方便偷懶。

 

基本思路:安裝2017版的通達OA,提取出對應的upload.php做個代碼對比,就能夠知道補丁的修改點了。

安裝後在webroot目錄下獲得了全部代碼,不過代碼都是zend54加密的,需要解密。

由於文件比較多,可以使用SeayDzendj本地解密:https://www.webshell.cc/6379.html

之後使用Bcompare進行代碼比對,發現代碼有兩處變動。

 

第一處:

 

第二處:

 

 

分析:

第一處代碼的修改使原本可以不包含的auth.php變成了必定包含。那我們來看一下auth.php的內容。

auth.php

 

顯然,auth.php是用來檢驗用戶登錄狀態的。那麼在修復前,是if..else語句,該檢測可以被繞過,從而在未登錄的狀態下執行後續的文件上傳操作。

 

第二處代碼的修改則是多了一句

if (strlen(urldecode($_FILES['ATTACHMENT']['name'])) != strlen($_FILES['ATTACHMENT']['name']))

 {

        $_FILES['ATTACHMENT']['name'] = urldecode($_FILES['ATTACHMENT']['name']);

  }

如果字符串解碼後的長度與原長度不同,說明可以被url解碼,那麼再url解碼,而不是直接解碼。

 

一開始懷疑是把shell.php文件名二次編碼後繞過上傳檢測,然後在其他調用上傳文件的頁面(例如個人文件移動)中被再次解碼,生成shell.php文件。 所以在此加入了檢測語句,防止文件名被二次解碼。但仔細一想,發現這根本沒什麼用呀,這裏的代碼解碼只進行了一次,無法檢測3次、4次url編碼的文件名,並不能達到攔截文件名的效果。

 

網站內隨便找點上傳功能試試,也沒發現什麼端倪

這邊疑惑了很久,搞不清它的意義。後來覺得可能這並不是漏洞的修補點,因爲通達OA2017也有很多個小版本,可能小版本更新中早就已經加入了這段代碼,而非此次的補丁(後續對OA v11的分析也印證了這一點)。

 

在url檢測後,緊接着是文件上傳。

$ATTACHMENTS = upload("ATTACHMENT", $MODULE, false);

嘗試構造上傳請求,必要的變量名有P,DEST_UID,以及一個文件的變量名ATTACHMENT。

同時上傳參數值以及文件內容的請求比較少見,那麼此時作爲一個垃圾安全人員,如何POST值的同時加入文件上傳這種問題,顯然是要百度解決的。百度後,我們可以構造類似於下面這種形式的頁面代碼,抓取其請求進行修改。

<form  action="user.do" id="upfile"  method="post" enctype="multipart/form-data">

     <input type="hidden"  name="x2" value="12334" />

     <input type="file"  name="x1" value="瀏覽圖片" />

     <input type="submit" value="tijiao"/>

</form>

 

構造請求包,上傳成功。文件保存於\MYOA\attach\im\2003\目錄,在原來的文件名前面加了一長串隨機值,而且該目錄不存在web目錄下。 嘗試在文件名中插入../測試是否能目錄穿越,也不行。

 

我們再看代碼,之前提到的第二處代碼修改點的外圍是if ($UPLOAD_MODE == '1') {  }。

那麼就想着嘗試$UPLOAD_MODE == '1'來看看會出現什麼情況,結果發現$UPLOAD_MODE這個變量是憑空出現的!  先不慌,猜想可能是從其他文件中包含過來的,或者是某種全局變量啥的。 全局搜索字段“UPLOAD_MODE”,也是什麼都沒有。  那麼這個變量是量子力學?平行宇宙?  

可以通過“變量覆蓋漏洞”的知識點聯想“變量註冊”這個概念,參考:https://www.cnblogs.com/xiaozi/p/7768580.html

例如當register_globals=On的時候,可以直接使用$id來代替$_GET['id'] $_POST['id']接受傳遞過來的值。 當然不只這一種方式,此處也並非是這種方式,就不再浪費時間去找相關的代碼了。 實踐出真知,直接上傳測試。

 

變量$UPLOAD_MODE註冊成功,上傳文件成功,實際在目錄中的文件名是1123589952.12345.gif,還是仍舊保存在原來的目錄。

不過只能上傳小馬文件,卻無法觸發,這就很難受。繼續分析一下,會發現一個奇怪的地方,upload.php所在的目錄\ispirit\im中的代碼似乎是一條獨立的系統,並沒有用於其web頁面。

這im其實是負責通達OA的客戶端程序-辦公精靈的後端接口。從菜單欄-附件程序可以下載

                                         

 

下載了客戶端,不過客戶端一直連不上服務。而且也爲這2017版的漏洞點花了太多時間,性價比不高,就暫時停止了。

 

回過頭來看最新版v11,我們以2017的upload.php漏洞進行切入。

查看ispirit/im/upload.php,通過對比可以發現只有一個修改點,和2017版本的補丁一樣,是對auth.php的包含問題。而之前在2017版本的困惑的第二個修改點,在此卻並不是補丁,代碼前後一致,說明之前的想法是對的,這裏並不是漏洞觸發點。

 

 

然後我們對所有的補丁的文件做個統計,會發現大部分的代碼修改點都是一致的

general\appbuilder\modules\officeproduct\models\OfficeProducts.php

general\netdisk\api.php

general\person_info\avatar\avatar.upload.php

general\picture\upload_new.php

general\reportshop\design\report\set_report.php

general\reportshop\workshop\report\crscell\set_report.php

general\setting_guide\update.php

general\index_simple_submit.inc.php

inc\attendance\attend.clock.funcs.php

inc\interface\interface.netdisk.funcs.php

inc\interface\interface.picture.funcs.php

inc\utility_file.php

module\AIP\upload.aip.php

task\clean\slow_logs.inc.php

 

上述14個文件的代碼修改點:rename函數更改爲td_rename

 

general\system\attachment\position\add.php

general\system\attachment\position\update.php

上述2個文件的代碼中皆增加了如下代碼檢測,檢測路徑中的關鍵字。

ispirit\im\upload.php  包含auth.php,檢測登錄狀態。

 

    \ispirit\interface\gateway.php增加了..檢測,防止跨目錄包含

 

mobile\inc\funcs.php

general\netdisk\swfupload_new.php

這兩個文件改動有些大,不再討論。

 

分析一下最廣泛的補丁:rename函數更改爲td_rename,

   rename()是php的自帶函數,rename(oldname,newname)函數重命名文件或目錄。若成功,則該函數返回 true。若失敗,則返回 false。rename也是支持路徑輸入的,即可以移動文件,跨目錄改名。

td_name()則是在inc\utility_file.php中被定義的:

function td_rename($oldname, $newname)

{

if (!is_uploadable($newname)) {

Message(_("禁止"), _("禁止創建此類型文件"));

Button_Back();

exit();

}



if (file_exists($oldname)) {

return rename($oldname, $newname);

}

else {

Message(_("錯誤"), _("原文件不存在"));

Button_Back();

exit();

}

}

 

有了is_uploadable()的檢測, 其定義也在inc\utility_file.php中,禁止改名後的新文件以php爲後綴。

 

 

     很容易聯想到在ispirit\im\upload.php中存在無需登錄的文件上傳,只不過文件名稱被做了限制,而且保存目錄不在網站目錄下。 這時候配合rename()的改名和移動目錄的能力,就能把文件名改爲xx.php並放入網站目錄下。不過遺憾的是,這個改名操作的漏洞點需要用戶在登錄狀態下才能,降低了安全風險。 rename()帶來的安全隱患應該普遍存在於各個web項目中。

 

參考:

UnicodeSec出了一個分析,https://www.cnblogs.com/potatsoSec/p/12516234.html

在ispirit/interface/gateway.php中存在的文件包含漏洞可以通過包含日誌的形式觸發,且無需登錄。

poc:

首先構造url並訪問,在日誌中寫入一句話

/ispirit/interface/gateway.php?json={}&aa=<?php file_put_contents('1.php','hello world');?>

 

然後通過如下url進行文件包含利用

/ispirit/interface/gateway.php?json={}&url=../../ispirit/../../nginx/logs/oa.access.log

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章