執行摘要

Slow Pisces(又名 Jade Sleet、TraderTraitor、PUKCHONG)是北韓國家支持的威脅組織,主要著重於為北韓政權創造財政收入,通常以加密貨幣領域相關的大型組織為攻擊目標。本文分析他們的活動,我們認為這與最近的加密貨幣搶劫案有關。

在此活動中, Slow Pisces 在 LinkedIn 上與加密貨幣開發人員接洽,冒充潛在雇主,並傳送偽裝成「編碼挑戰」的惡意軟體。這些挑戰需要開發人員執行已經遭到惡意植入的專案案,進而在系統上安裝我們命名為 RN Loader 和 RN Stealer 的惡意軟體。

據報導,該組織在 2023 年從加密貨幣產業竊取超過 10 億美元。他們使用各種方法達成此目標,包括虛假的交易應用程式、透過節點套件管理員 (Node Package Manager ,NPM) 散佈的惡意軟體,以及供應鏈攻擊

2024 年 12 月,一家日本加密貨幣公司的 3.08 億美元失竊案被FBI 將歸咎 於 Slow Pisces。最近,該組織因涉嫌參與一起杜拜加密貨幣交易所高達 15 億美元的盜竊案 而成為頭條新聞。

針對這波行動,我們已將威脅情報分享給 GitHub 和 LinkedIn 的分析團隊,以協助下架攻擊者的相關帳號和惡意程式碼儲存庫。

他們提供以下聲明作為回應:

GitHub 和 LinkedIn 因這些惡意帳戶違反各自的服務條款而將其移除。在我們所有的產品中,我們使用自動化技術,結合調查專家團隊和使用者舉報機制來打擊不良行為者和強制執行服務條款。我們將不斷地優化和改善我們的流程,並鼓勵我們的客戶和會員用戶主動舉報任何可疑的活動。

其他資訊

本報告詳細介紹 Slow Pisces 如何將惡意軟體隱藏在其發送的編碼挑戰中,並描述該團體的後續工具,目的是讓更多業界人士更了解此威脅。

透過我們的具有進階 URL 篩選進階 DNS 安全性訂閱的新一代防火牆,Palo Alto Networks 客戶可以更好地免受本文討論的威脅。

如果您認為自己可能已受到危害或有緊急情況,請聯絡 Unit 42 事件回應團隊.

相關 Unit 42 課題 Cryptocurrency, DPRK

技術分析

我們對這項活動的可視性大致遵循三個步驟,如下圖 1 所示。

說明涉及 PDF 誘餌、GitHub 儲存庫和 C2 伺服器的網路安全威脅的圖表。圖中顯示 1) PDF 檔案 (例如工作說明和試題表) 充當誘餌;2) GitHub JavaScript 和 Python 儲存庫具有多種外部 API,可能會擷取惡意資料;以及 3) C2 伺服器配置為在特定情況下傳送良性資料或惡意有效載荷。包含 Palo Alto Networks 和 UNIT 42 標誌。
圖 1.Slow Pisces「編碼挑戰」活動概述。

第 1 階段 - PDF 誘餌

Slow Pisces 一開始在 LinkedIn 上冒充招聘人員與潛在目標接觸,並傳送一份看似無害的 PDF 檔案給他們,內容是一份工作職缺的描述,如下圖 2 所示。如果潛在目標提出申請,攻擊者就會向他們提出編碼程式挑戰作為應徵的一部分,其中包括多個任務或題目,要求應徵者在本地端下載並執行專案程式碼。

圖片中並排顯示兩個文件。左邊是 UX 設計團隊協調員的「工作描述」。右邊是一份「問題表」,包含與使用者經驗 (UX) 設計相關的技術與一般問題。
圖 2.良性 PDF 誘餌。

我們觀察到 Slow Pisces 冒充多個企業組織進行這些誘騙,這些組織主要是在加密貨幣領域。攻擊者提供的城市挑戰說明文件包括一般的軟體開發任務和一個「真實專案」的編碼挑戰,並連結到下圖 3 所示的 GitHub 程式碼儲存庫。

標題為 「Coding and Problem-Solving Skills With Real Project」 的文件截圖。其中包含一個 GitHub 儲存庫的連結,並概述了一項涉及來自 API 來源的比特幣和以太坊匯率的編碼任務。文中要求透過增加更多的市場 API 以及改善程式碼中的網路通訊來強化該專案。
圖 3.PDF 誘惑中包含的「真實專案」編碼挑戰。

第 2 階段 - GitHub 儲存庫

Slow Pisces 以 GitHub 程式碼儲存庫中的專案為目標,提出所謂的編碼挑戰。程式碼儲存庫包含改編自開放源碼專案的程式碼,其表面功能是用來檢視和分析下列類型的資料:

  • 股票市場資訊
  • 歐洲足球聯賽的統計資料
  • 天氣數據
  • 加密貨幣價格

攻擊者主要使用 Python 或 JavaScript 的專案,推測是根據受害者申請的職務類型來調整,分別對應前端或後端開發者的技能偏好。我們在曾經在這次活動中也看到少數以 Java 為基礎的儲存庫案例,,其中兩個帳號冒充了一個名為 jCoin 的加密貨幣應用程式。

這種顯示攻擊者可能會依據目標偏好的程式語言,按需要來建立儲存庫。因此,該團體更常使用在加密貨幣領域更受歡迎的語言,例如 JavaScript 和 Python。因此我們合理推測還可能存在尚未被發現的、使用其他程式語言的惡意儲存庫

階段 3a - Python 儲存庫

2024 年底,該小組使用下圖 4 所示的專案,標題為「Stocks Pattern Analyzer」,其程式碼大多改編自合法的開源儲存庫

名為「Stocks Pattern Analyzer」的 GitHub 儲存庫截圖,左側顯示檔案結構,右側顯示 README 檔案內容,說明如何直接執行應用程式和使用 Docker。
圖 4."Stocks Pattern Analyzer" Python 儲存庫。

程式碼儲存庫中的大部分程式碼都是看似正常無害的。當目標嘗試根據問題表執行專案時,程式會從三個遠端位置擷取資料:

  • hxxps://en.wikipedia[.]org/wiki/List_of_S%26P_500_companies
  • hxxps://en.wikipedia[.]org/wiki/Currency_pair
  • hxxps://en.stockslab[.]org/symbols/sp500

其中兩個 URL 從 Wikipedia 的合法網址取得資料。第三個 URL 使用由 Slow Pisces 控制的惡意網域。這種「混合合法與惡意來源」的手法,是該組織在 Python 攻擊儲存庫中很常見的模式。

為了提高隱匿性,這個惡意的命令與控制 (C2) 伺服器被設定為模仿合法來源的格式。在這種情況下,其使用 .en 子域和 .org 頂層網域 (TLD),就像我們在上面看到的合法維基百科網域一樣。

YAML 反序列化攻擊 (Deserialization)

Slow Pisces 可以簡單地直接將惡意軟體置入程式碼儲存庫,或使用 Python 內建的 evalexec 函數執行 C2 伺服器上的程式碼。然而,這些技術很容易被偵測出來容易被人工審查或防毒引擎識別。

取而代之的方法是,Slow Pisces 會先確保 C2 伺服器回應看似正常的應用程式資料。例如 S&P 500 公司的代號清單,格式為標準的 JSON。

只有當確認連線者是預期的攻擊對象,(很可能是根據 IP 位址、地理位置、時間和 HTTP 請求標頭),C2才會發送真正的惡意載荷。相較於廣泛的網路釣魚活動,攻擊者專注於透過 LinkedIn 聯繫的個人,讓該組織可以嚴格控制攻擊流程,並只向預期的受害者傳送載荷。

為了避免可疑的 evalexec 函數,Slow Pisces 使用 YAML 反序列化來執行其載荷,如圖 5 所示。

定義函式 『fetch_symbols』 的 Python 程式碼畫面,該函式使用 API 呼叫從 S&P 500 擷取股票符號,處理不同的內容類型,並根據其內容類型處理回應。最後一行的部分以紅色方塊突出顯示。
圖 5.Python 程式碼顯示 Slow Pisces 惡意軟體使用 YAML 反序列化的入口點。

此程式碼透過 HTTPS 從 C2 伺服器取得資料,並檢查 Content-Type 回應標頭。如果標頭指示 JSON 資料(application/json),程式碼會解析並將 JSON 傳回給應用程式。

如果回應顯示 YAML 資料(application/yaml),程式碼會使用 PyYAML 套件中的 yaml.load() 函數來解析資料。這個函數本質上是不安全的,PyYAML 官方文件明確建議 針對不可信的輸入應該使用yaml.safe_load(),以避免執行任意程式碼。

YAML 通常用於撰寫設定檔,例如下圖所示的範例:

然而, yaml.load() 可以還原(deserialize)任意的 Python 物件,而不僅限於純粹的的 YAML 格式資料。舉例來說,以下 Python 程式碼會列印數字 0-4:

如果使用 yaml.dump() 將此程式碼序列化,則會變成以下內容:

當這些資料傳給 yaml.load() 時,它會執行原始程式碼:range(0, 5)

這類攻擊手法突顯一個行為特徵點:若惡意的YAML載荷使用Python內建函式,則 反序列化的惡意軟體就會包含 !!python/object/apply:builtins

表 1 中的下列階段主要存在於記憶體中(in-memory),通常不會在硬碟上留下任何足跡。為了協助資安社群偵測和提高警覺,我們已將這些載荷上傳至 VirusTotal。YAML 反序列化載荷會執行我們根據在 RN Stealer 中觀測到的 C2 權仗格式而命名為 RN Loader 和 RN Stealer 的惡意軟體,我們會在下文討論。

階段 SHA256 雜湊
YAML 反序列化承載 47e997b85ed3f51d2b1d37a6a61ae72185d9ceaf519e2fdb53bf7e761b7bc08f
RN Loader 937c533bddb8bbcd908b62f2bf48e5bc11160505df20fea91d9600d999eafa79
RN Stealer e89bf606fbed8f68127934758726bbb5e68e751427f3bcad3ddf883cb2b50fc7

表 1.Python 儲存庫承載。

Slow Pisces 的攻擊鏈中, YAML 反序列化載荷首先會在受害者的主目錄中建立一個名為 Public的資料夾,並在該目錄中建立一個名為 __init__ .py 的新檔案。這個檔案包含了經過 Base64 解碼的資料,這些資料構成了下個階段的惡意程式 (RN Loader),並會立刻被執行。

RN Loader

這個新建立的 RN Loader 檔案位於 ~/Public/__init__.py,會在執行後自行刪除以確保它只存在於記憶體中。它會透過 HTTPS 將受害機器和作業系統的基本資訊傳送至 en.stockslab[.]org 的同一個 C2,接著是一個命令迴圈,其中包含表 2 中的下列選項。

代碼 說明
0 睡眠 20 秒
1 對傳送的內容進行 Base64 解碼,並將其儲存至 Windows 的 init.dll 檔案或所有其他作業系統的 init 檔案。

設定環境變數 X_DATABASE_NAME 為空白字串。

使用 ctypes.cdll.LoadLibrary 載入並執行下載的 DLL。

2 Base64 解碼傳送的內容,並使用 Python 內建的 exec 執行。
3 對傳送內容和參數進行 Base64 解碼。內容會儲存到 dockerd 檔案,而參數則儲存為 docker-init

然後,dockerd 會在一個新的進程中執行,並提供 docker-init 作為命令列的參數。

9 終止執行。

表 2.RN Loader 指令表。

表 2 中使用選項 1 和選項 3 的指令迴圈的承載目前尚不清楚,很可能是由特定條件觸發。然而,我們復原一個由選項 2 傳送的 Python-based 資訊竊取程式,我們將此惡意軟體追蹤為 RN Stealer。

RN Stealer

RN竊取程式首先會產生一個隨機受害者 ID,隨後在與 C2 伺服器的所有通訊中作為 Cookie 使用。然後,它會向伺服器請求 XOR 金鑰,以加密外洩的資料。

與 C2 伺服器的通訊透過 HTTPS 進行,使用 Base64 編碼權仗來識別要求和回應類型。分析的承載包括四種權杖類型:

  • R0 - 請求 XOR 金鑰
  • R64 - 資料外洩
  • R128 - 竊取壓縮資料
  • R256 - 資訊竊取完成

這些權杖類型的格式—字母 R 跟整數 N—導致我們為此載荷命名。我們稱承載為 RN Stealer,前一階段為 RN Loader。

我們從 macOS 系統中復原這個 RN Loader 範例的指令碼。因此,威脅作者量身打造此範例,以竊取 MacOS 裝置的特定資訊,包括

  • 受害者基本資訊:使用者名稱、機器名稱和架構
  • 已安裝的應用程式
  • 目錄清單和受害者主目錄的頂層內容
  • 在 macOS 系統中儲存已儲存憑證的 login.keychain-db 檔案
  • 儲存的 SSH 金鑰
  • 適用於 AWS、Kubernetes 和 Google Cloud 的組態檔案

RN Stealer 收集的資料可能會決定是否需要持續存取。如果是的話,我們可以推斷這個 Python 感染鏈的步驟如下:

  1. C2 伺服器會根據未知標準檢查指標受害者。有效的受害者會收到 YAML 反序列化載荷。無效的受害者會收到無害的 JSON 資料。
  2. 解序列化載荷會與 C2 伺服器建立指令迴圈,滲透受害者的基本資訊,並透過表 2 中的選項代碼 2 傳送自訂 Python 資訊竊取程式。
  3. 資訊竊取程式會收集更詳細的受害者資訊,攻擊者很可能利用這些資訊來決定是否需要不斷地存取。
    1. 如果需求不斷地存取,C2 伺服器會透過選項代碼 1 或 3 傳送承載。
    2. 如果不再需要存取權限,選項代碼 9 會終止惡意軟體的執行,移除所有存取權限,因為承載只存在於記憶體中。

第 3b 階段 - JavaScript 儲存庫

如果目標受害者申請的是 JavaScript 職缺,他們可能會遇到「加密貨幣儀表板(Cryptocurrency Dashboard)」專案,類似於下圖 6 的範例。

GitHub 儲存庫名為「加密貨幣儀表板」的截圖,其中顯示了 README.md 檔案。此 README 包括以下部分: 功能、安裝、使用、專案結構、組態、相依性和授權。它將專案描述為使用 Node.js、Express 和 EJS 建立的應用程式,可顯示各種加密貨幣的即時和歷史資料。
圖 6.JavaScript 儲存庫。

此應用程式包含一個 .env 設定檔案,裡面定義了 C2 和合法的資料來源:

  • PORT=3000
  • COINGECKO_API_URL=hxxps://api.coingecko[.]com/api/v3
  • JQUERY_API_URL=hxxps://update.jquerycloud[.]io/api/v1

COINGECKO_API_URL 值用於擷取加密貨幣儀表板的資料,而 JQUERY_API_URL 值則代表由 Slow Pisces 所控制的 C2 伺服器。與 Python 儲存庫相似,JavaScript C2 伺服器只會將載荷傳送給已驗證的目標,否則只會回傳一個版本號碼。

此儲存庫使用嵌入式 JavaScript (EJS) 模板工具,並將 來自C2 伺服器的回應傳送至 ejs.render() 函式,如下圖 7 所示。

顯示 JavaScript 程式碼片段的截圖。它包含一個註解和一個函式呼叫,用來呈現具有每頁設定和項目的首頁。res.render 以紅色方塊突出顯示。
圖 7.JavaScript 程式碼使用 EJS render 函數顯示 Slow Pisces 惡意軟體的入口點。

這種用法與 yaml.load()一樣,是 Slow Pisces 用來隱藏來自 C2 伺服器執行任意程式碼的另一種技術,而且這種方法可能只有在檢視有效的載荷時才會顯現出來。

EJS render 函數接受各種參數,其中之一稱為檢視選項(view options)。在此物件內,可以透過escapeFunction 鍵來提供並執行任意 JavaScript 程式碼。

台灣研究人員 Huli 在 CTF 發表的文章中討論過這個漏洞如何導致任意程式碼執行的技術細節。不過,我們可以充分了解的是,如圖 8 所示結構的 payload 在傳給 ejs.render() 時,位於escapeFunction 中的程式碼被執行。

涉及函數的 JavaScript 程式碼片段截圖,其中「escapeFunction」以紅色方塊突出顯示。
圖 8.部分 EJS 渲染承載。

不幸的是,我們無法完全還原這個惡意載荷的全部內容。因此,我們只能推測其行為,包括使用者的主目錄下會建立一個新的 .jql目錄 ,並在其中放置一個名為 helper.js 的檔案,內容為 Base64 編碼的資料。

基礎建設

下圖 9 中的時間軸詳述 2024 年 2 月至 2025 年 2 月這場行動中所使用的 C2 基礎架構,並按所支援的儲存庫類型 (JavaScript 或 Python) 分類。

追蹤 JavaScript 指令與控制項 (上方,黃色標籤) 和 Python 指令與控制項 (下方,橘色標籤) 的基礎架構時間軸。時間線從 2024 年第一季末開始,一直到 2025 年第二季。
圖 9.C2 基礎設施時間表。

如前所述,此活動基礎架構中的網域名稱,常仿效其搭配使用的合法資料來源格式,例如 api 或 cdn等子網域。截至本文發表前,我們至今仍持續發現與此攻擊活動相關的基礎建設。

總結

本報告介紹了 Slow Pisces 近期的攻擊活動,透過 LinkedIn 冒充招聘人員,針對加密貨幣領域的開發人員進行惡意的編碼挑戰。雖然我們無法復原 JavaScript 儲存庫的完整攻擊鏈,但 Python 版本的活動提供兩個新的惡意載荷,我們將其命名為 RN Loader 和 RN Stealer。

以這種方式使用 LinkedIn 和 GitHub 並非獨一無二。多個隸屬於朝鮮的團體,例如 Alluring PiscesContagious Interview也使用了類似的手段。

這些組織在運作上沒有實際的行動重疊。然而,值得注意的是,這些活動使用類似的初始感染方式。

Slow Pisces 在作業安全方面與其他組織相比更為出色。每個階段的載荷傳送都受到嚴密的控管,多數只存在於記憶體中。而該集團的後期工具也只會在必要時才會部署。

該小組特別使用兩種隱藏功能的技術:

  • YAML 反序列化
  • EJS的 escapeFunction

這兩種技術都會大大妨礙分析、偵測和追捕工作的難度。同樣地,加密貨幣領域中相對較新或經驗較淺的開發人員也很難將這些儲存庫識別為惡意儲存庫。

根據有關加密貨幣竊案的公開報告,這項活動似乎非常成功,而且很可能在 2025 年持續下去。雖然這篇文章強調 YAML deserialization 和 EJS escapeFunction 荷載的兩個潛在偵測機會,但最有效的緩解方法仍然是嚴格分隔公司和個人裝置的使用。這將有助於防止企業系統受到有針對性的社交工程攻擊。

Palo Alto Networks 保護和緩解功能

Palo Alto Networks 客戶可透過下列產品,更好地保護免受上述威脅:

如果您認為自己可能已受到攻擊或有緊急情況,請聯絡 Unit 42 事件回應團隊或致電

  • 北美洲:免費電話:+1 (866) 486-4842 (866.4.unit42)
  • 英國:+44.20.3743.3660
  • 歐洲和中東:+31.20.299.3130
  • 亞洲:+65.6983.8730
  • 日本:+81.50.1790.0200
  • 澳洲:+61.2.4062.7950
  • 印度:00080005045107

Palo Alto Networks 跟我們的 Cyber Threat Alliance (CTA) 同業分享這些發現。CTA 會員利用這些情報,迅速為客戶部署保護措施,並有系統地瓦解惡意的網路行為者。進一步瞭解 Cyber Threat Alliance.

入侵指標

網域 IP 位址 初見 最後看到 儲存庫
getstockprice[.]com 70.34.245[.]118 2025-02-03 2025-02-20 Python
cdn[.]clubinfo[.]io 5.206.227[.]51 2025-01-21 2025-02-19 Python
getstockprice[.]info 131.226.2[.]120 2025-01-21 2025-01-23 Python
api[.]stockinfo[.]io 136.244.93[.]248 2024-10-30 2024-11-11 Python
cdn[.]logoeye[.]net 54.39.83[.]151 2024-10-29 2024-11-03 Python
en[.]wfinance[.]org 195.133.26[.]32 2024-10-12 2024-11-01 Python
en[.]stocksindex[.]org 185.236.231[.]224 2024-09-11 2024-10-04 Python
cdn[.]jqueryversion[.]net 194.11.226[.]16 2024-08-23 2024-09-23 JavaScript
en[.]stockslab[.]org 91.103.140[.]191 2024-08-19 2024-09-12 Python
update[.]jquerycloud[.]io 192.236.199[.]57 2024-07-03 2024-08-22 JavaScript
cdn[.]soccerlab[.]io 146.70.124[.]70 2024-08-07 2024-08-21 Python
api[.]coinpricehub[.]io 45.141.58[.]40 2024-05-06 2024-08-06 Java
cdn[.]leaguehub[.]net 5.133.9[.]252 2024-07-15 2024-07-21 Python
cdn[.]clublogos[.]io 146.19.173[.]29 2024-06-24 2024-07-12 Python
api[.]jquery-release[.]com 146.70.125[.]120 2024-06-10 2024-06-28 JavaScript
cdn[.]logosports[.]net 185.62.58[.]74 2024-05-08 2024-06-23 Python
skypredict[.]org 80.82.77[.]80 2024-05-06 2024-06-16 JavaScript
api[.]bitzone[.]io 192.248.145[.]210 2024-04-25 2024-05-13 Python
weatherdatahub[.]org 194.15.112[.]200 2024-04-05 2024-05-03 JavaScript
api[.]ethzone[.]io 91.234.199[.]90 2024-04-16 2024-04-24 Python
api[.]fivebit[.]io 185.216.144[.]41 2024-04-08 2024-04-14 Python
blockprices[.]io 91.193.18[.]201 2024-03-15 2024-04-09 JavaScript
api[.]coinhar[.]io 185.62.58[.]122 2024-03-26 2024-04-09 Python
mavenradar[.]com 23.254.230[.]253 2024-02-21 2024-03-26 JavaScript
indobit[.]io 146.70.88[.]126 2024-03-19 2024-03-20 Python
api[.]thaibit[.]io 79.137.248[.]193 2024-03-07 2024-03-09 Python
chainanalyser[.]com 38.180.62[.]135 2024-02-23 2024-03-06 JavaScript

其他資源

 

Enlarged Image