天天看點

【審計思路】如何快速定位SQLMS注入漏洞?

作者:KaliMa

0x00 前言

MCMS是政府、教育等其他行業常用的CMS,應用廣泛,但是底層的代碼中仍然遺留不少的問題。這篇文章主要針對SQL注入進行審計并探讨如何快速定位SQL注入漏洞,以及其他工具的應用。

MCMS,是完整開源的Java CMS!基于SpringBoot 2架構,前端基于vue、element ui。每兩個月收集issues問題并更新版本,為開發者提供上百套免費模闆,同時提供适用的插件(文章、商城、微信、論壇、會員、評論、支付、積分、工作流、任務排程等…),一套簡單好用的開源系統、一整套優質的開源生态内容體系。銘飛的使命就是降低開發成本提高開發效率,提供全方位的企業級開發解決方案。

0x01 審計環境

Mingsoft MCMS v5.2.8
Mysql 8.0.29
Openjdk 19.0.1
           

0x02 審計思路

現代做代碼審計的工具市面上已經有很多了,在拿到源碼的時候,第一時間當然是先使用工具進行掃描,節省人工時間。盡管有fortify、奇安信代碼衛士這些工具在,但避免不一些纰漏,仍然需要人工經驗的判斷。

利用自動化代碼審計工具

這裡我們使用 fortify 工具對源碼進行掃描,記錄了我遇到的兩個問題。該 fortify 工具為收費工具,本文不提供破解版的下載下傳方式。

【一一幫助安全學習,所有資源關注我,私信回複“資料”擷取一一】

①網絡安全學習路線

②20份滲透測試電子書

③安全攻防357頁筆記

④50份安全攻防面試指南

⑤安全紅隊滲透工具包

⑥網絡安全必備書籍

⑦100個漏洞實戰案例

⑧安全大廠内部視訊資源

⑨曆年CTF奪旗賽題解析

1.反編譯 jar 包

使用 fortify 導入MCMS 源碼進行代碼審計,但效果往往不如意。因為這一套源碼使用 Maven 作為項目管理工具軟體,其中包括依賴管理,MCMS項目依賴的jar包都是遠端拉取的。其中net.mingsoft.ms-base、ms-basic、ms-mdiy為底層邏輯代碼。拉取的時候是以jar包的形式存在的,而自動化工具不會對jar包進行掃描。

【審計思路】如何快速定位SQLMS注入漏洞?

我們可以将 jar 包重命名為 zip,然後解壓就能獲得 class 檔案。但 fortify 同樣不會掃描 class 檔案,我們需要進一步反編譯。這裡我們可以使用 jadx 進行反編譯。

【審計思路】如何快速定位SQLMS注入漏洞?

我們可以直接打開 jar 檔案,通過快捷鍵 Control+S 将反編譯後的資源進行儲存。

【審計思路】如何快速定位SQLMS注入漏洞?

導出之後就是 java 檔案,是可以被掃描的檔案類型。

【審計思路】如何快速定位SQLMS注入漏洞?

2.不掃描 JS 檔案

在掃描代碼的實踐中,我遇到 JS 檔案數量過多情況,導緻整體的掃描進度大幅度拉長,這不是我想要的。

找到 fortify/Core/config 目錄下的 fortify-sca.properties

【審計思路】如何快速定位SQLMS注入漏洞?

其中 com.fortify.sca.DefaultFileTypes 一項規定了被掃描檔案的類型。我們把其中的 ,js删掉就可以了。

【審計思路】如何快速定位SQLMS注入漏洞?

人工審計SQL注入思路

造成SQL注入一般需要滿足以下兩個條件:

(1)輸入參數内容使用者可控。

(2)直接或間接拼入SQL語句執行。

且在執行SQL語句時有不同的方式:

(1)直接使用 JDBC 的類方法。

針對這種執行SQL語句的方式,我們可以全局搜尋 SELECT、DELETE、UPDATE 等 SQL 關鍵詞或者搜尋 Statement、PreparedStatement方法名稱來定位執行語句的地方。

(2)使用 MyBatis 持久化層作SQL語句執行代理。

MyBatis 持久化層中一般使用 #{} 在底層實作上使用 “?”作為占位符,是預編譯的機制。在實踐過程中,類似order by等不能使用單引号的地方都不可以使用預編譯,轉而使用 ${}直接拼接到SQL語句中。一般這種情況需要手動增加内容的嚴格過濾步驟。是以盡管預編譯很強大但也有用不上的地方,而這些地方就是我們的突破口。

0x03 審計過程

由上面的描述可以知道使用 ${}的地方往往可能存在SQL注入風險,是以我們審計過程中可以直接全局搜尋${}。

1. 底層映射存在注入漏洞引發多個前台注入

原因

在SQL持久化層 IBaseDao.xml 檔案中可以看到綁定id 為 sqlWhere 的 Sql 映射裡使用了 ${} 導緻存在SQL注入的風險。

【審計思路】如何快速定位SQLMS注入漏洞?

第一處 GET類型

在 IDictDao.xml 中引入 IBaseDao.xml 映射語句。

【審計思路】如何快速定位SQLMS注入漏洞?

在 IDictBiz 這個業務層是繼承了 IBaseBiz 進而有 query 确定傳回類型為 DictEntity。

【審計思路】如何快速定位SQLMS注入漏洞?

在控制層 web/DictAction.class 中可以看到這裡請求資料包的資料變成了實體,然後直接傳入 dictBiz.query 中。

【審計思路】如何快速定位SQLMS注入漏洞?

我們請求這個接口時,所有傳入的參數與值會别當作 DictEntity,是以這裡直接傳 sqlWhere 即可。

【審計思路】如何快速定位SQLMS注入漏洞?
sqlWhere的值為 [{"action":"","field":"extractvalue(0x7e,concat(0x7e,(database())))","el":"eq","model":"contentTitle","name":"文章标題","type":"input","value":"a"}]
           

第二處 GET 類型

在 IDictDao.xml 中引入 IBaseDao.xml 映射語句。id 為 queryExcludeApp。

【審計思路】如何快速定位SQLMS注入漏洞?

在控制層 web/DictAction.class 中可以看到這裡請求資料包的資料變成了實體,然後直接傳入 dictBiz.queryExcludeApp中。

【審計思路】如何快速定位SQLMS注入漏洞?

同樣的這裡所有傳入的參數與值會别當作 DictEntity,存在同樣的問題。

【審計思路】如何快速定位SQLMS注入漏洞?

第三處 POST類型

在 ICategoryDao.xml 中引入 IBaseDao.xml 映射語句。

【審計思路】如何快速定位SQLMS注入漏洞?

在控制層 web/CategoryAction.java 中可以看到這裡請求資料包的資料變成了實體,然後直接傳入categoryBiz.query 中。

【審計思路】如何快速定位SQLMS注入漏洞?

這裡的實體類型有了變化,但不妨礙我們傳入 sqlWhere導緻漏洞的執行。

【審計思路】如何快速定位SQLMS注入漏洞?

第四處 POST類型

在 IContentDao.xml 中引入 IBaseDao.xml 映射語句。

【審計思路】如何快速定位SQLMS注入漏洞?

在控制層 web/ContentAction.java 中可以看到這裡請求資料包的資料變成了實體,然後直接傳入contentBiz.query 中。

【審計思路】如何快速定位SQLMS注入漏洞?

隻要引入之後,如果沒有過濾都是存在漏洞的。

【審計思路】如何快速定位SQLMS注入漏洞?

2. 背景自定義模型任意SQL語句執行

在持久化層 IBaseDao.xml 中存在一處綁定了 id 為 excuteSql 的 SQL 操作語句。該地方直接執行了傳入 SQL 語句。

【審計思路】如何快速定位SQLMS注入漏洞?

持久化層代理 IBaseDao.class 寫好了對應 IBaseDao.xml 的接口

【審計思路】如何快速定位SQLMS注入漏洞?

IModelDao.class 繼承了 IBaseDao 确定了類型為 ModelEntity

【審計思路】如何快速定位SQLMS注入漏洞?
【審計思路】如何快速定位SQLMS注入漏洞?

業務層 IModelBiz.class 定義了一些接口

【審計思路】如何快速定位SQLMS注入漏洞?

業務實作層 ModelBizImpl.class 實作了 IModelBiz.class 接口,通過閱讀代碼,可以發現實際上在 importModel 函數裡面使用了 IModelDao.class 中的 excuteSql 方法。

【審計思路】如何快速定位SQLMS注入漏洞?

在控制層 ModelAction.class 中 importJson 函數裡調用了 ModelBizImpl.class 的 importModel 函數。

【審計思路】如何快速定位SQLMS注入漏洞?

該漏洞産生位置存在背景自定義模型的導入功能處,要使用該功能需要到 https://code.mingsoft.net/ 生成代碼。

【審計思路】如何快速定位SQLMS注入漏洞?

建立業務表單 ——> 拖動表單元件 ——> 填寫字段名和預設值 ——> 生成代碼

【審計思路】如何快速定位SQLMS注入漏洞?

可以看到生成的自定義模型代碼,我們複制出來将 sql 字段的 value 改成我們自定義的即可。

【審計思路】如何快速定位SQLMS注入漏洞?

任意都行沒有過濾和限制,語句的行是通過 split(';')來分割的。

【審計思路】如何快速定位SQLMS注入漏洞?

這個其實是MCMS的核心業務,無法避免的使用,是以隻要使用 MCMS 擁有自定義模型的導入功能的權限就可以利用SQL注入擷取資料或者系統權限。

3.校驗參數接口前台SQL注入

因為使用了 mybatis 架構這裡就全局搜使用 $ 進行拼接的,發現在/net/mingsoft/ms-base/2.1.13/ms-base-2.1.13.jar!/net/mingsoft/base/dao/IBaseDao.xml

【審計思路】如何快速定位SQLMS注入漏洞?

進一步跟進queryBySQL

【審計思路】如何快速定位SQLMS注入漏洞?

檢視對應接口中的實作方法

【審計思路】如何快速定位SQLMS注入漏洞?

然後在/net/mingsoft/base/biz/impl/BaseBizImpl.java這裡進行了重寫queryBySQL,然後調用getDao().queryBySQL

【審計思路】如何快速定位SQLMS注入漏洞?

然後發現在/net/mingsoft/basic/action/BaseAction.class#validated 驗證的時候進行調用

【審計思路】如何快速定位SQLMS注入漏洞?

繼續跟,這時候隻要找到前端路由中能調用validated就可以了,然後發現在/net/mingsoft/ms-mdiy/2.1.13.1/ms-mdiy-2.1.13.1-sources.jar!/net/mingsoft/mdiy/action/PageAction.java#verify

調用了validated方法

【審計思路】如何快速定位SQLMS注入漏洞?

尋找路由,通過分析我們這個是個GetMapping 然後參數fieldName、fieldValue、id、idName 随便構造一下,最開始我們看到的key對應的就是前端傳進來的fieldName

【審計思路】如何快速定位SQLMS注入漏洞?
http://127.0.0.1:8008/ms/mdiy/page/verify.do?fieldName=1;select/**/if(substring((select/**/database()),1,4)='mcms',sleep(5),1)/**/and/**/1&fieldValue=b&id=c&idName=1
fieldName`是傳入了 `${key}直接拼接到SQL語句導緻SQL注入。
           
【審計思路】如何快速定位SQLMS注入漏洞?

0x04 總結

代碼審計論證了預編譯不是萬能的,否則不會出現這麼多的 SQL 注入漏洞。在不能使用預編譯處理參數值,隻能通過拼接進行操作的地方,除了手工寫過比對危險字元濾函數之外還有什麼方法嗎?我們還可以嚴格要求傳入的參數類型,例如數字的地方将使用者輸入的内容進行強制轉化成 int 不行就報錯處理,這種稱之為表單過濾層。如果我們的代碼體積龐大無法花費大量人力去排查漏洞存在,可以購買安全公司的代碼審計服務和WAF防火牆産品。

0x05 參考

*   [https://gitee.com/mingSoft/MCMS/issues/I5OWGU](https://gitee.com/mingSoft/MCMS/issues/I5OWGU)
*   [https://gitee.com/mingSoft/MCMS/issues/I5X1U2](https://gitee.com/mingSoft/MCMS/
                
【審計思路】如何快速定位SQLMS注入漏洞?

繼續閱讀