[記錄] 遊戲橘子讓你的beanfun! 帳號隱私無所遁形

文章推薦指數: 80 %
投票人數:10人

Landing Page 判斷客戶端裝置是否為手機,若是就轉向以 beanfunapp:// 開頭的URL,如果已安裝Beanfun APP 將會自動開啟;若沒安裝APP 或在電腦版上在3 秒 ... 頁面 首頁 關於這裡 訂閱我/聯絡我 交換連結 跑跑資訊站 文章分類 公告/更新 影片/音樂 未分類 生活/紀錄 開發/技術 Discuz! WordPress 筆記/分享 資源/設計 雲端/時事 Chrome擴充功能 新知/資訊 社群網站 雲端服務 電腦/軟體 Android 實用工具 桌布彙整 社群 LAY‧Blog›筆記/分享›開發/技術›[記錄]遊戲橘子讓你的beanfun!帳號隱私無所遁形,人人皆可自由存取 有鑑於遊戲橘子旗下越來越多遊戲會推出導向BeanfunAPP才能進行的活動,所以就養成了會稍微追蹤一下每個活動網頁運作方式的習慣, 跑跑卡丁車在10/16推出了萬聖節系列的網頁活動,一個是典型的、直接移植韓服開發的萬聖節輪盤活動,因為運作方式一樣就沒特別去研究, 另一個是橘子自己開發,名為「萬聖節抽鬼牌」的全新活動,這個活動就官方設定,只能透過掃描QRCode後在Beanfun(樂豆)官方手機APP上進行, 但其實實際上就只是透過一連串的網址轉向到活動網頁中,只要知道最終的目標網址,就算不透過BeanfunAPP開啟也能訪問, 而偉哉營運團隊似乎是貪圖方便或是沒有資安觀念,竟然完全信任由客戶端發送的任何請求,沒有針對參數或身分進行任何驗證查核的程序, 導致所有樂豆用戶的帳號隱私可能通通落入有心人士手中,同時也可能影響到所有跑跑玩家的活動參與權益。

先來找出活動入口 活動網頁必須從同樣是萬聖節活動的「萬聖節蜂蜜罐」活動網頁中點擊「前往抽鬼牌」後,掃描出現的QRCode進入, 在掃描或解析圖片後得到的網址會是: https://beanfunstor.blob.core.windows.net/redirect/appCheck.html?url=beanfunapp://Q/h5/w_id/a52659c027334c719685dbc88fb2f158_widget%3Furl%3Dhttps%253a%252f%252fbfweb.beanfun.com%252fAutoRedirect%253fActivityType%253d0%2526RedirectUrl%253dhttps%25253a%25252f%25252fevent.beanfun.com%25252fkartrider%25252fE20201016_H5%25252findex.aspx 這個網址進入後包含了三層的網址轉向: LandingPage判斷客戶端裝置是否為手機,若是就轉向以 beanfunapp://開頭的URL,如果已安裝BeanfunAPP將會自動開啟;若沒安裝APP或在電腦版上在3秒後會彈出提示框詢問是否進入APP下載頁 在BeanfunAPP中開啟WebView,載入Loading網頁 在Loading網頁中判斷UserAgent有沒有包含BeanGo,有的話就前往目標網頁,沒有則導向Beanfun首頁 最終可以得到目標活動網頁為: https://event.beanfun.com/kartrider/E20201016_H5/index.aspx 此時就能直接在瀏覽器中訪問此網址,就算不使用BeanfunAPP、不用在APP內綁定樂豆帳號也能存取活動網頁了。

  活動運作方式解析 現在就能直接在電腦Chrome上訪問活動網頁,雖然一進入就會得到「請使用beanfun!應用程式(P02)」的錯誤訊息, 但這段訊息可謂佛系阻擋,在Console裡執行$.gbox.close();就能把訊息關掉,並且能接著使用其他功能。

這時候似乎已經可以開始進行「抽鬼牌」這個動作,任選網頁中兩張牌就會出現抽牌結果,但實際看一下API請求: 其實是完全沒有帶上和帳號相關的參數的,也就是這個結果也只能拿來測試用,重新整理再選一次也會拿到一樣的結果。

  那麼到底有哪些參數是這個活動內使用到的API所需的呢? 看一下網頁原始碼就能發現,在最下方有一個區塊是專門讓後端吐資料的區塊: 這塊的內容只有在網頁是從BeanfunAPP內開啟時,後端會根據APP內目前所選的綁定帳號Session來抓帳號資訊並填入。

而其中ErrMsg如果有值,網頁一載入就會彈框顯示並且不會執行後續判斷帳號的部分;IsJoin則是判斷目前的帳號是否已報名活動。

接著下面引入了兩個Script檔 default.js 和 e20201016H5.js是這次活動的核心檔案,為了避免線上檔案被更動我已經將原版檔案備份到[Gist]中,可以對照參考。

  接著來就要研究這次的主角,也就是活動會使用到的API,相關的函式都放在e20201016H5.js這支JS裡, 可以看到進到網頁後會做三件事,首先判斷上面提到的ErrMsg,接著會去檢查Beango這個和APP內WebView相關的環境變數, 最後再去檢查主帳號是否已綁定過遊戲帳號,有的話就檢查今天是否已有抽牌紀錄,沒有的話就彈出帳號選擇視窗。

插播一段吐槽時間,BGO.check_app_exist的callback裡面寫了根據APP環境檢查結果決定是否彈窗阻擋後續操作的邏輯, 但這裡面的的return是寫在callback的函式裡,對整個流程阻擋毫無效果,所以不管判斷結果如何一定會繼續執行後面的IsJoin判斷,是在寫爽的?   只需要Beanfun主帳號就能拉出帳號資料 回到正題,關鍵的地方來了,getGameAccountList 這個函式在做的事就是這次讓你的帳號資訊被攤在陽光下的開端, 它會去打這個請求取得遊戲帳號列表: POST/kartrider/E20201016_H5/index.aspx/GetGameAccountListHTTP/1.1 Host:event.beanfun.com Content-Type:application/json;charset=UTF-8 {"MainAccountID":BEANFUN_USERNAME} 其中JSON裡的 BEANFUN_USERNAME就是後端會吐到原始碼裡面的MainAccountID,也就是登入Beanfun時使用的主帳號, 如果在非BeanfunAPP的環境中瀏覽,MainAccountID只會收到空字串,不過只要填入任意帳號都能正常被後端接受,整個過程是沒有任何驗證流程的, 換句話說,只要你手上有任何玩家的Beanfun主帳號,不需要密碼或其他資訊,你都可以輕易取得這個人的帳號資料, 而BeanfunAPP過去主打、說得天花亂墜的帳號「最高防護」功能在此刻也完全發揮不了作用。

更好笑的是,橘子旗下遊戲過去還常常主動請玩家將自己的Beanfun帳號「詔告天下」, 隨便抓兩個跑跑卡丁車的粉絲團活動來看看,第一個是要得獎者公開留言自己的帳號(Source): 上面這篇只釣(?)出了三個帳號,不甚理想,那接下來看看第二個活動(Source): 這個活動就成功釣出了上百位玩家的Beanfun帳號。

  而這個這個GetGameAccountList的API打出去之後會收到什麼呢? 這裡就應景從上面的留言列表中挑一個帳號來測試,得到以下結果: ResultData內會包含這隻樂豆帳號內已經建立的跑跑卡丁車帳號列表(每個帳號最多有五隻), 並能看到個帳號的以下資訊: ServiceAccountID:遊戲登入帳號(整合Beanfun登入前在跑跑登入窗用的,整合後才創的帳號為自動產生的TE開頭帳號) ServiceAccountSN:遊戲帳號編號(有遞增連續性) ServiceAccountDisplayName:遊戲顯示名稱(啟動遊戲列表顯示的自訂名稱) ExpirationTime:遊戲最後登出時間(2000/01/01代表沒有登出記錄) UsedPoints:累積使用過的樂豆點(單一遊戲帳號累積) UsedServicePoints:累積使用過的專用點數(跑跑過去活動贈送過遊戲專用點數) CreateTime:遊戲帳號創立時間(非遊戲角色) LastUsedTime:上次啟動遊戲時間(其實就等於取得OTP的時間,不管最後有沒有啟動遊戲) CreateTime、LastUsedTime是以Timestamp的型態回傳(+0時區),可以使用EpochConverter轉換成當地日期格式。

  雖然可以看到累積消費點數的資訊還滿酷的,就算在官網登入帳號也查不到, 拿來查自己的是無所謂,但誰會希望這些隱私被莫名其妙的路人看見呢?   免驗證程序幫其他玩家報名參加活動 更扯的事情來了,除了能查詢帳號資料外,這次活動還能免驗證直接幫其他玩家報名參加, 等於可以以任意玩家的身分來存取活動,這個真的相當恐怖,這次的活動是選定帳號後就無法更換, 而一個樂豆主帳號只能綁定一個遊戲帳號,活動獲得的獎勵只會發送至該遊戲帳號中, 只能慶幸跑跑卡丁車的玩家本身就不多,如果這些漏洞是發生在大型遊戲,可能已經天下大亂了。

  根據default.js以及 e20201016H5.js 兩支檔案裡的函式,可以知道整個活動報名的流程是: 如果此帳號尚未報名,一進頁面時呼叫GetGameAccountList 取得帳號列表,並渲染出選項顯示在畫面上 選擇要報名的帳號後,點擊[確定]會呼叫GetGameAccountData取得該帳號的報名所需資訊,畫面顯示確認視窗 點擊[確定]確認選擇後,呼叫InsertJoinLog完成報名程序   第一步驟可以直接按照上一個區塊的流程進行來獲取遊戲帳號列表,由於安全問題這裡會改用測試帳號來示範, 最終從中挑選一隻遊戲帳號,這裡拿「周子瑜玩跑跑」這隻來測試,記下稍後會使用到的參數ServiceAccountID。

{ "__type":"E20201016_H5_GameAccountModel", "ServiceAccountID":"TE875d88831472763645", "ServiceAccountSN":"2474212", "ServiceAccountDisplayName":"周子瑜玩跑跑", "Type":"N", "ChargeRule":"0W", "ExpirationTime":"2000/1/1上午12:00:00", "UsedPoints":0, "NewAccountFlag":true, "UsedServicePoints":0, "CreateTime":"/Date(1478184482013)/", "LastUsedTime":"/Date(1478184482013)/", "Visible":"1" } 接著來取得這隻帳號的報名所需資訊,等同於在網頁上操作時確認報名帳號的步驟,先進行以下請求: POST/kartrider/E20201016_H5/index.aspx/GetGameAccountDataHTTP/1.1 Host:event.beanfun.com Content-Type:application/json;charset=UTF-8 {"ServiceAccount":ServiceAccountID} 在這裡的ServiceAccountID就是上面的遊戲登入帳號TE875d88831472763645, 送出請求後,如果帳號是存在的,就會得到以下回應內容: 其中ResultData除了包含nid 遊戲登入帳號外,還多了rid這個是遊戲內的角色名稱(這個也滿扯的可以直接拉到遊戲ID,這裡是剛好和顯示名稱一樣), 以及oid可能是遊戲角色創立順序編號、DBLocation似乎是帳號資料存放的資料庫,但實際上到底是什麼並不重要,因為只需要原封不動地把這塊資料再丟回去後端就行了, 接著要進行最後的「報名」動作,執行以下請求: POST/kartrider/E20201016_H5/index.aspx/InsertJoinLogHTTP/1.1 Host:event.beanfun.com Content-Type:application/json;charset=UTF-8 { "StarAccount":"", "MainAccountID":BEANFUN_USERNAME, "ServiceAccount":ServiceAccountID, "AccountData":{ "__type":"E20201016_H5_GameAccountDataModel", "oid":134263107, "nid":"TE875d88831472763645", "rid":"周子瑜玩跑跑", "DBLocation":"00" } } MainAccountID 帶入樂豆主帳號、ServiceAccount帶入遊戲登入帳號,而AccountData就是帶入剛剛拿到的ResultData整個物件, 至於StarAccount我到最後還是沒找出它的內容和用途,且經測試StarAccount和ServiceAccount兩個欄位直接傳入空字串也能報名成功(??), 成功報名之後就會收到以下格式的回傳內容,其中 ResultData欄位回傳的3660就是此帳號的報名排序, 如果報名失敗會直接在ResultMessage帶入原因,通常是該樂豆主帳號已經選擇過遊戲帳號了。

後來測試把 AccountData固定使用同一組遊戲帳號的資料,只修改樂豆主帳號竟然也能報名成功, 這代表可以把不同的樂豆主帳號都綁定非主帳號底下的遊戲帳號,一個你得獎我領獎的概念。

  報名成功後就能接著參加活動,也就是抽撲克牌,每天都能進行一次,是呼叫PlayPoker這隻API, 比較麻煩的是同樣的API要呼叫兩次,分別是第一張和第二張牌: POST/kartrider/E20201016_H5/index.aspx/PlayPokerHTTP/1.1 Host:event.beanfun.com Content-Type:application/json;charset=UTF-8 { "PlayCount":1, "StockID":"", "StarAccount":"", "MainAccountID":BEANFUN_USERNAME, "ServiceAccount":ServiceAccountID } 上面的PlayCount就是抽取的張數,分別要填入 1和2 進行兩次請求才能完成當日抽牌活動, StockID是遊戲內的道具商品編號,官方是寫抽第二張牌時才要帶入,但經測試後端不會吃到這個值,所以不需填寫, 其餘參數和報名時使用的一模一樣,但MainAccountID 和ServiceAccount兩個欄位的值必須和報名使用的一樣(兩兩配對)才能請求成功,成功抽牌後就會獲得以下結果: 第一張牌一定是遊戲道具或點數,第二張牌大部分都是鬼牌,就是槓龜,Rate應該是出現機率,但只有第一次請求會顯示實際機率,重複呼叫後機率都會變成100%, 或是只要看ResultData.IsWin就知道有沒有贏,但有沒有贏不是這次的重點,這次的重點是為什麼可以這麼輕易的就使用別人的身分來進行這個活動...   總結一下 所以透過這次抽鬼牌活動的漏洞,所有人都可以做到以下這些事: 查詢樂豆主帳號已開通的跑跑卡丁車遊戲帳號列表、遊戲帳號資訊 查詢玩家遊戲帳號在遊戲內對應的角色名稱 幫其他玩家報名活動,並綁定進行活動的遊戲帳號 將其他玩家的樂豆主帳號綁定自己的遊戲帳號 以其他玩家的身分來進行每日抽牌活動 不受裝置、數量限制的無限報名和參加活動 本文到此為止的操作都只要透過一個Beanfun主帳號就能達成,完全沒有經過其他認證或授權的程序,你能相信這個產品來自一個營運了20幾年的大公司嗎? 查了一下遊戲橘子內部光是和資安相關的工程師就有資安顧問、資安監控、資安管理、資安滲透測試四種職位,但似乎都沒有在這次的專案中發揮到專業, 橘子旗下遊戲的帳號數量少說也有上千萬個,如果每款遊戲的活動都用同樣的品質來開發,等於將這些玩家的隱私暴露在風險中,甚至有可能被大量外洩,帳號安全毫無保障, 另外也要提醒大家這種涉及到重要資料或金錢交易的帳號,為了安全起見千萬不要隨意公開在網路上,橘子自己就做了最大的錯誤示範。

  後記I 本文以上提到的安全問題於10/16發現,經過確認及驗證後,已經於10/19下午2點經由遊戲橘子客服中心回報, 同日晚上9點左右橘子非常迅速地來電表示上述提到的問題都已經修復完成,營運團隊很重視玩家的帳號安全blablabla..., 然後不斷感謝我回報了這個漏洞,接著詢問能不能不要在網路上公佈相關細節(因為我在回報信件裡有提到在官方修復完成後會公開), 但基於玩家的立場我覺得還是有必要讓大家知道這件事,這多少也能拋磚引玉讓更多玩家能一起監督後續的活動內容, 所以還是選擇將整個事件的原委給記錄下來,讓大家能知道活動開始後的這四天自己的帳號曾經遭受什麼樣的風險。

順帶一提,經過測試目前以上提到的幾隻API的確已經會正常限制非透過BeanfunAPP授權發送的請求了:   後記II 10/20早上又收到橘子來電,還有兩通,但我沒接到,也沒打算回撥,而且後續也沒再收到其他來電了,事情應該落幕。

分享 推文 分享 標籤:樂豆漏洞資安跑跑卡丁車遊戲橘子 想隨時追蹤最新資訊?歡迎使用E-mail訂閱最新文章» 訂閱 或是直接訂閱RSS» 您或許會感興趣的文章 隨機推薦 利用程式碼顯示E-mail,讓機器人看的到抓不到![遊記]六天五夜東、北部之旅YouTube推出全新頻道介面,快來搶先試用!如何在網站中插入Facebook留言框?不一樣的15歲生日![下載]打電話、傳簡訊完全免費的即時通訊APP-Line 共有3則迴響 布丁布丁吃布丁 #1 @ 2310月,2020 太專業 回覆 路人999 #2 @ 26月,2021 網站設計師表示,寫在JS上,都會被人看+漏洞:thinking:。

回覆 Lay # @ 26月,2021 要寫是能寫,只是後端還是要驗證,他們可能以為網頁是內嵌在APP裡面就沒人看的到。

回覆 發表迴響 點擊這裡以取消回覆 * * :laughing: :heart_eyes: :wink: :thinking: :thumbsup: :sleeping: :frown: :cry: 送出留言 歡迎訂閱本站文章 訂閱 最新文章 [筆記]和Bitly說再見,遷移至自行管理的Shlink短網址服務TWICE-MOONLIGHT(月光)繁中認聲歌詞[中英對照]TWICE-SCIENTIST(科學家)繁中認聲歌詞&應援詞[中韓對照][踩坑筆記]排除Windows10升級Windows11時出現的各種錯誤TWICE-TheFeels繁中認聲歌詞[中英對照]拯救雲端硬碟資料,將GSuite教育版帳號中的檔案轉移至其他Google帳號TWICE-AlcoholFree繁中認聲歌詞&應援詞[中韓對照]IU-Celebrity繁中歌詞[中韓對照] 出版書籍 文章分類文章分類 選取分類 公告/更新  (14) 影片/音樂  (28) 未分類  (1) 生活/紀錄  (9) 開發/技術  (24)    Discuz!  (2)    WordPress  (7)    筆記/分享  (5)    資源/設計  (10) 雲端/時事  (59)    Chrome擴充功能  (14)    新知/資訊  (19)    社群網站  (13)    雲端服務  (12) 電腦/軟體  (39)    Android  (4)    實用工具  (30)    桌布彙整  (5) 文章彙整 文章彙整 選取月份 2021年11月 2021年10月 2021年9月 2021年6月 2021年1月 2020年12月 2020年10月 2020年9月 2020年6月 2019年9月 2019年8月 2019年5月 2019年4月 2019年1月 2018年11月 2018年7月 2018年5月 2018年4月 2018年1月 2017年12月 2017年11月 2017年8月 2017年7月 2017年6月 2017年5月 2017年4月 2017年2月 2017年1月 2016年10月 2016年8月 2016年7月 2016年5月 2016年4月 2016年3月 2015年12月 2015年10月 2015年8月 2015年7月 2015年6月 2014年9月 2014年6月 2013年12月 2013年11月 2013年10月 2013年7月 2013年6月 2013年4月 2013年3月 2013年2月 2013年1月 2012年12月 2012年11月 2012年10月 2012年9月 2012年8月 2012年7月 2012年4月 2012年3月 2012年2月 2012年1月 2011年12月 2011年11月 2011年10月 2011年9月 2011年8月 2011年7月 2011年6月 2011年5月 2011年4月 2011年3月 2011年1月 2010年12月 2010年11月 2010年10月 贊助連結 關於子女監護權判定| 想找高雄徵信公司但不知道怎麼找| 請問徵信社意思是| 想找外遇診療室幫你療傷| 首選徵信社在幹嘛| 徵信社行情標準表| 來徵信社阿宅教您反詐騙| 究竟怎麼防徵信社呢| 標籤雲3C Android Breakthrough Chrome CSS Facebook Firefox Google HTML InternetExplorer javascript Jusin.tv Line PHP Plurk RaidCall Social TWICE트와이스 Twitch.tv Windows WordPress YouTube 下載 佈景主題 免安裝 免費 免費軟體 原創翻譯 圖示 工具 影音 應援詞 應用程式 技巧 插件 桌布 歌詞 破解 素材 網頁設計 線上 聊天 舞台字幕 認聲 遊戲 合作邀請歡迎來信洽詢WordPress佈景主題/外掛、Discuz模板/插件客製化或修改服務, 全台最大的跑跑卡丁車社區「跑跑資訊站」也歡迎贊助商及廣告合作夥伴來信洽詢, 若有興趣歡迎[聯絡我],我將會盡快回覆您。

歡迎追蹤粉絲團 ‧助聽器公司‧坐月子中心‧汽車音響‧日本北海道‧雷射近視‧新多益準備方式-英代外語‧布沙發‧西藏旅行社‧泰國旅遊‧婚攝‧中華航空‧視訊會議‧北海道旅行社‧奇寶SEO團隊‧Spinluxhighmastlightingsystem‧媽媽禮服出租‧婚紗拍攝‧壓克力雷射切割加工‧摩洛哥旅遊‧澳洲遊學代辦推薦-喬順國際‧壁燈‧西班牙旅行社‧USB3.1CTYPE‧歐洲澳捷旅遊推薦旅行社-吉光旅遊‧美國大學碩士留學-新絲路留遊學‧花蓮名產台灣麻糬-大保比‧北九州由布院之森觀光列車團-新進旅行社‧室內設計施工‧法國旅行社推薦‧隆乳手術照片‧菲律賓TOP10語言學校推薦-瘋英文‧菲律賓語言學校推薦TOP10‧台北精緻搬家推薦‧菲律賓遊學語言學校費用‧眼袋類型‧血糖機價格‧為何越來越多人選擇隱形牙套?‧三層A楞搬家紙箱-祥優搬家‧ 文章看完了,歡迎按個讚追蹤Facebook! 已經按讚了



請為這篇文章評分?