Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2023-00143
- Vendor: 批踢踢實業坊
- Title: 批踢踢實業坊 邏輯漏洞
- Introduction: 存在邏輯漏洞及洩漏 stack 資訊
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
未回報修補狀況
-
未複測
-
公開
處理歷程
- 2023/03/21 15:47:00 : 新提交 (由 愛麗絲 更新此狀態)
- 2023/03/22 10:41:38 : 審核中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/03/26 20:24:01 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/04/24 12:55:54 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/04/24 12:55:54 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/04/24 12:55:54 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/05/16 17:52:24 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/05/16 17:52:40 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2023/06/04 03:00:02 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
- ZDID:ZD-2023-00143
- 通報者:fxfxxxfxx (愛麗絲)
- 風險:低
- 類型:邏輯漏洞 (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
相關網址
及使用 https://github.com/ptt/pttbbs 的站台
敘述
板主等具有舉辦樂透功能的帳號可以讓P幣(該網站的虛擬幣)不正常增加
以及可以 leak 出部份 stack 上的資訊
原始碼位於 https://github.com/ptt/pttbbs
在 mbbsd/gamble.c 中
可以發現,如果使用者停在購買樂透的頁面
此時若板主結束當下的樂透並重新開一個新的樂透的話
使用者此時便能以過去的價格購買到下一個樂透
因此若板主先開一個單價 10 元的樂透
另一個使用者停在購買頁面後
板主重新開一個單價 10000 元的樂透
便能將 P幣 翻 (1000 * 0.95) 倍
還有另一個增長更為快速的方法
樂透的紀錄共有兩個檔案
分別是紀錄各選項數目的 FN_TICKET_OUTCOME
以及紀錄使用者選什麼選項的 FN_TICKET_USER
假設目前使用者A、B分別能購買 X, Y份樂透
以下是流程:
- 板主開啟有兩個選項的樂透
- 使用者A 停留在購買頁面
- 板主結束樂透並開啟新的有三個選項的樂透
- 使用者B 購買 Y-1 份樂透(選項3)
- 使用者A 購買 X 份樂透(選項2)
- 使用者B 購買 1 份樂透(選項3)
- 板主開獎(選項3)
關鍵在第 5 步時,使用者A 會因為只寫入前兩個選項的結果而造成
在 FN_TICKET_OUTCOME 中選項3遺失
mbbsd/gamble.c:157:
ftruncate(fileno(fp), 0);
rewind(fp);
for (i = 0; i < count; i++)
fprintf(fp, "%lld ", ticket[i]);
fflush(fp);
變數 count 是使用者A 當時的選項數(2)
所以第 4 步使用者B 的選項3 便會在 FN_TICKET_OUTCOME 中遺失
在板主開獎時,賠率會是 X/1 = 1:X
但在發放獎金時使用的 FN_TICKET_USER 仍然有使用者B的紀錄
因此使用者B可以拿到 ((Y-1)X + 1X) * 0.95 = 0.95XY
以上兩種方法並不衝突,所以複合後可以達到 950XY
下圖是我用原始碼在本地實驗的結果,並沒有在網站上使用
(可以看到上方選項3 只有1份,但下方發獎金時發了23+1份)
另外,若板主先開啟四個選項的樂透再開二個選項的樂透的話
便能讓使用者在後者下出不存在的第四個選項
在開獎印出選項名稱時,此時 betname[mybet] 是未初始化的 char[30]
因此可以 leak 出 stack 上的資訊
此後若能控制 control flow
便有機會藉此資訊達成 RCE
mbbsd/gamble:466:
} else {
if (fp)
fprintf(fp, " %-*s 買了 %3d 張 %s\n" ,
IDLEN, userid, i, betname[mybet]);
continue;
}