問題
遊戲伺服器(Lua/Skynet)的 Redis 資料被攻擊者篡改,將遊戲狀態改為免費中獎狀態,導致異常獲利。最終整個資料庫被清空。
嘗試的防禦手段(均被繞過)
- Checksum 驗證 — 對 Redis 內容加上雜湊驗證,被繞過
- AES 加密儲存 — 將 Redis 資料加密後儲存,仍被篡改成功
- 移至記憶體 — 不讀取 Redis,資料存在 process 記憶體中,讓攻擊者無法直接改 Redis
最後整個資料庫仍被刪除。
推測攻擊路徑
- 攻擊入口:同內網另一台 PHP server 存在漏洞
- PHP server 與 Lua server(game-A、game-B、gate-[A-B])處於同一內網
- 攻擊者透過 PHP server 取得內網存取權後,可能直接讀取 Lua server 上的原始碼與設定檔
- 因此 checksum 算法與 AES key 對攻擊者是透明的,所有應用層加密形同虛設
關鍵洞察
加密保護的前提是 key 不能外洩。 當攻擊者已在內網且能讀取原始碼時,所有硬編碼或存在設定檔的 key 都會被拿到,加密只是多一道他知道答案的謎題。
真正應該處理的是入侵點(PHP server 的漏洞),而不是在症狀上加防護。從症狀端防禦,攻擊者只需跟著你的防禦策略升級攻擊手段。
未解之謎
- 攻擊者確切如何從 PHP server 橫向移動到 Lua server
- 如何確認 Lua source code 的洩漏路徑
- 目前採取放任狀態,因系統停擺的損失大於持續被盜
後續方向(尚未實施)
- 徹底稽核 PHP server 的漏洞,這才是根本
- 內網隔離,PHP server 不應能直接存取 game server 的檔案系統
- Secret 管理:key 不應存在原始碼或可被讀取的設定檔中