從SQL注入到Getshell


確認版本

首先可以通過接口來確認一下當前禪道的版本。

http://example.com/index.php?mode=getconfig

 

SQL注入分析

網上之前有過一個9.1.2orderBy函數的分析,但是沒想到9.2.1也存在此問題,(2018.3.2號看到目前最新版本是9.8.1)。

出問題的地方是此文件的orderBy函數:\lib\base\dao\dao.class.php

對於limit后未做嚴格的過濾與判斷,然后拼接到了order by后面導致產生注入.

$order = join(',', $orders) . ' ' . $limit;

看了一下9.8.1的修補是對limit進行正則限制,但是事實上感覺此處正則是寫了一個bug,比如正常調用orderBy($order)的時候,其中$orderabc desc limit 1,1的時候,進入$limit則是limit 1,1,導致匹配失敗。

如果想要造成前台注入(無需登錄)的話,就得先看看禪道開放了哪些接口,看是否有調用orderBy函數。

\zentao\module\common\model.php

其中的if($module == 'block' and $method == 'main') return true;,也就是本次漏洞的主角,繼續跟進。

\zentao\module\block\control.php

首先看__construct中,$this->selfCall是在驗證referer的值,如果為真的話則后面的if將不會進入die語句里面

接下來跟進main函數,可以看到最后的$func = 'print' . ucfirst($code) . 'Block';,會對一些函數進行調用,與此同時,我們搜索orderBy的調用的時候可以發現printCaseBlock函數的存在

\zentao\module\block\control.php

所以前台注入的整個過程便比較清晰了,那么如何利用?

SQL注入利用

回過頭來,因為禪道有windows直接的一鍵化安裝程序,其數據庫使用的也是root權限,導致可直接導出shell,但是如果沒有這么高權限的時候,對於這個注入應該如何出數據。

禪道是支持多語句的,這也為后面的利用提供方便。

注入出數據庫名和表段名后,當我想繼續注入出用戶賬號密碼的時候,意外地發現沒有出數據。

sql = 'select 12345 from zt_user'

還是沒有出數據,猜測是管理員改了表前綴,所以想去通過information_schema查詢一下表名,但是意外地發現,也不能讀取?難道被刪了?但是我還是想知道一下表前綴。

請求的時候加了一個單引號,並且加上referer,看一下報錯信息。

因為PDO的關系,SQL中的表名是%s替代的,所以未能夠得到庫名。

那么就利用報錯去得到當前SQl語句里面查詢的表名,比如利用polygon函數。

此注入點可以理解為limit后的注入點,因為使用多語句的話,報錯效果不明顯,所以就直接在limit后面進行注入。

 

上圖為本地測試,但是limit的注入和mysql版本還有一些關系,目前網上的payload僅限於低版本才可報錯注入出數據,很不幸運的是,目標使用的是高版本mysql。

那既然可以多語句,在不能用information_schema的情況下,可以通過下面語法來進行盲注:

show table status where name = 'xxx' and sleep(2)

寫到py里面的payload是這樣的

經過一番折騰發現,表前綴就是默認的zt_,但是為啥又不能夠讀取到用戶數據呢?

仔細看到禪道里面的orderBy函數,發現做了過濾。

把下划線給過濾掉了,那這種在多語句下,可以利用mysql的預查詢來繞過,值得注意的是,這個版本語法大小寫敏感。

注入出admin密碼的時候,驚喜地發現不能解開,無奈之下,只能先拿到一個普通賬號。

Getshell

禪道在防止getshell方面還花了一點心思,曾經挖到一個可以任意寫文件getshell(最新版本還存在這段代碼),不過需要的權限是管理員權限。

看了一下禪道里面人員組織架構情況,有研發、項目經理、產品經理,高層管理,系統管理員等角色,其中系統管理員雖然密碼解不開,但是我們可以去解密一下高層管理的密碼,因為這個角色的權限是可以修改某用戶的用戶組權限。在高層管理賬號中,我們可以將一個普通賬號修改為管理員。

接下來就是寫文件Getshell:

/xampp/zentaopro/module/api/control.php

可以看到是進入了call_user_func_array,也就是我們可以任意實例化一個module方法,方法的參數也是可控的,可以通過,來分割參數。

/zentaopro/module/editor/model.php

在editor中是可以寫一個文件的,filePath可控,fileContent也是可控的,這下就是可以任意寫一個文件。

Exp:

但是問題又來了,前面報錯里面得到的路徑目錄感覺像是做了權限(這里繞彎了,路徑少加了一個www,所以以為是沒權限寫),最終從數據庫中的zt_file獲取上傳文件的路徑,然后再將shell寫入當中才得以結束。

總結

對於order by的漏洞如何進行防御的時候,我覺得上面代碼在部分上有可取之處。

1、去掉limit部分,然后限制格式

2、然后循環對每個字段進行反引號的添加

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM