Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2016-00074
- Vendor: 錢櫃企業股份有限公司
- Title: 錢櫃 KTV 架構問題導致任意點歌、訊息發送、SQL Injection 等多個漏洞
- Introduction: 錢櫃 KTV 架構問題導致任意點歌、訊息發送、SQL Injection 等多個漏洞
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
已修補
-
未複測
-
公開
處理歷程
- 2016/05/17 16:18:47 : 新提交 (由 Orange 更新此狀態)
- 2016/05/17 16:20:03 : 新提交 (由 Orange 更新此狀態)
- 2016/05/17 16:45:49 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2016/05/30 17:52:54 : 通報未回應 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2016/05/30 17:53:06 : 通報已回應 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2016/05/30 17:53:26 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2016/09/19 23:33:19 : 已修補 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2017/02/02 03:00:02 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
- ZDID:ZD-2016-00074
- 通報者:orange (Orange)
- 風險:高
- 類型:邏輯漏洞 (Logic Flaws)
參考資料
漏洞說明: OWASP - Testing for business logic
https://www.owasp.org/index.php/Testing_for_business_logic
漏洞說明: CWE-840: Business Logic Errors
https://cwe.mitre.org/data/definitions/840.html
相關網址
http://mobileappv2.cashboxparty.com/WebService/SongService.asmx/LoginKeysSelect
http://mobileappv2.cashboxparty.com/WebService/Song.asmx/UseMyPartyMessageV2
敘述
很久很久以前,CrBoy 及 Orange 心血來潮唱歌時,發現
錢櫃有 App 可以用!
錢櫃有 App 可以用!
錢櫃有 App 可以用!
因此來始看一下錢櫃 App 有什麼好玩的!
錢櫃 App 可使用包廂內點歌系統右上角的四位數驗證碼來登入 App,並透過手機進行點歌、插歌,發送訊息到 KTV 包廂螢幕上等動作!
透過設置手機 Proxy 後擷取送驗證碼的請求發現得到錢櫃 App 使用 HTTP 連線至
>> http://mobileappv2.cashboxparty.com/WebService/SongService.asmx/LoginKeysSelect
>> POST={storeID : '',billNo: '',loginKey: 'ABCD'}
看到傳送內容時原思路為暴力破解 loginKey 嘗試爆出其他包廂的驗證碼,但四位數驗證碼範圍從 A-Z 0-9 共約 36^4 次方,似乎不太可能暴力破解出便先暫時放棄往其他的路嘗試。
將網址後端去掉,直接訪問
>> http://mobileappv2.cashboxparty.com/WebService/SongService.asmx
發現使用 ASP.NET 內建 WebService 實作,可以列出所有 WebService 方法,因此得到了更多的 undocumented API 可使用
(如圖 2.png)
在首頁原始碼中也發現了
>> http://mobileappv2.cashboxparty.com/WebService/PromoEventService.asmx
>> http://mobileappv2.cashboxparty.com/WebService/CommonWebService.asmx
>> http://mobileappv2.cashboxparty.com/WebService/MemberService.asmx
>> http://mobileappv2.cashboxparty.com/WebService/SongService.asmx
>> http://mobileappv2.cashboxparty.com/WebService/SettingsWebService.asmx
>> http://mobileappv2.cashboxparty.com/WebService/StoreInfo.asmx
此外網站使用的 IIS 未修補至最新,存在 IIS tilde 目錄列舉漏洞,詳細技術細節可參閱
>> https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf
(洩漏結果如圖 3.png)
因此又得到了
>> http://mobileappv2.cashboxparty.com/WebService/Booking.asmx
>> http://mobileappv2.cashboxparty.com/WebService/Store.asmx
>> http://mobileappv2.cashboxparty.com/WebService/AppRegisterWebService.asmx
透過以上 WebService 位置,從這些公開(或未公開)的 API 中來搜尋有何可使用!
首先從最一開始的 LoginKeysSelect 開始,LoginKeysSelect 共會吃三個參數,如
>> {storeID : '',billNo: '',loginKey: 'ABCD'}
在手機 App 與包廂機台進行綁定時只需提供 loginKey,驗證碼正確網站則回傳
>> {"StoreID":"0103","BillNo":"1605170010","LoginKey":"FA46","CreateDateTime":"2016/5/17 上午 12:55:48","ShowCreateDateTime":"2016-05-17 00:55:48","RoomNo":"603"}
其中 StoreID 猜測為錢櫃分店 ID,ID 與分店名稱對應可從 StoreInfo.asmx/SelectStoreInfo 中取得,RoomNo 代表位於哪間包廂,CreateDateTime 為開立包廂時間,billNo 猜測為帳單編號
從錢櫃架構設計中發現可以只提供 loginKey 反查 billNo,"猜測"也許也能單獨傳送其他參數反查 loginKey,經測試後發現無法只提供 storeID,反查 loginKey,但可以只提供 billNo 反查 loginKey,便開始將重心放置到 billNo 的規律破解上。
經過一陣思考後發現
>> 1605170010
前六碼代表當天日期,如 160517 代表 2016/05/17,而後四碼則為流水號,從 0001 到 9999,流水號每天凌晨十二點重置,而每天錢櫃客人包廂數量並不會將流水號佔滿,經測試一天帳單量約 300 ~ 400 組,因此如在 2016/05/18 當天,只需從 1605180001 嘗試至 1605180400 即可取得所有帳單驗證碼、分店、房間號碼、開立包廂時間。
有了所有帳單驗證碼後,即可透過錢櫃 App 內建功能對任意包廂插歌、點歌,並發送任意訊息!
在測試發送訊息時(只測試自己包廂),發現字數上限為 20 字,當超過時會被截斷。
另外,當訊息中存在 "_" 字元時,螢幕顯示的訊息永遠不會消失...
(解決方法只有請店員重開包廂機台。這應該不是資安問題而是程式有 BUG XD)
最後,在測試中額外找到兩個弱點
第一個弱點在 SongService.asmx/LoginKeysSelect,其中參數 storeID 存在 LINQ 的 SQL Injection。
第二個弱點在 Song.asmx/UseMyPartyMessageV2,在發送訊息的參數 partyMessage 上存在 MySQL 的 SQL Injection,同樣的網站存在兩種資料庫猜測為網頁端透過 WebService 將訊息傳送至控制錢櫃包廂的後端伺服器為 MySQL,錢櫃各包廂機台再去查詢是否有新訊息,因此網頁使用 SQL Server 而包廂機台伺服器使用 MySQL 較為合理。
弱點是在 Insert 中的 SQL Injection,因此如在手機傳送訊息填寫
>> \'+123+\'
則會在 KTV 包廂螢幕顯示 123
如要取得當前資料庫名稱長度,在訊息中輸入
>> \'+length(database())+\'
則會在 KTV 包廂螢幕顯示 4
(如圖 4.png)
如要取得當前資料庫內容,因 MySQL 無法使用 "+" 進行字串的串接,因此無法直接將所要的內容顯示在 KTV 包廂螢幕,不過可利用 ascii() 將字串轉成數字來幫助我們達成目的,如在訊息輸入
>> \' + (ascii(mid(database(),1,1))<<24)+(ascii(mid(database(),2,1))<<16)+(ascii(mid(database(),3,1))<<8)+(ascii(mid(database(),4,1))) + \'
則會在 KTV 包廂螢幕顯示 1128354632,再轉成 ASCII 為
>> CASH
(如圖 5.png)
代表當前資料庫名稱為 CASH
修補建議:
過濾或正確的使用 LINQ 及 Prepared Statement
使用隨機的 billNo 及 loginKey
工程師辛苦了...XD