サイバー犯罪

コーディングに挑戦する開発者を狙うSlow Pisces、カスタマイズされたPythonマルウェアを新たに導入

Clock Icon 3 分で読めます

エグゼクティブ・サマリー

Slow Pisces(別名Jade Sleet、TraderTraitor、PUKCHONG)は、北朝鮮の国家支援による脅威グループで、主に暗号通貨分野の大規模組織を標的にすることで、北朝鮮政権に収益をもたらすことに焦点を当てています。この記事では、最近の暗号通貨強盗に関連していると思われる彼らのキャンペーンを分析します。

このキャンペーンでは、Slow PiscesはLinkedIn上で暗号通貨開発者と関わり、潜在的な雇用者を装い、コーディング課題を装ったマルウェアを送信しました。これらの課題は、開発者に危険なプロジェクトの実行を要求し、私たちがRN LoaderとRN Stealerと名付けたマルウェアを使って開発者のシステムに感染させます。

このグループは、2023年に暗号通貨セクターから10億米ドル以上を盗んだと報告されている。彼らは、偽の取引アプリケーションノードパッケージマネージャ(NPM)を介して配布されるマルウェア、サプライチェーンの侵害など、さまざまな方法を使用してこれを達成した。

2024年12月、FBIはだとしている日本を拠点とする暗号通貨会社から3億800万ドルが盗まれたのはSlow Piscesによるもの。さらに最近では、ドバイの暗号通貨取引所から15億ドルが盗まれた事件への関与が疑われ、大きな話題となった。

我々は脅威インテリジェンスをGitHubとLinkedInのアナリストと共有し、関連するアカウントとリポジトリを削除した。

これに対し、彼らは次のような声明を発表した:

GitHubとLinkedInは、それぞれの利用規約に違反したこれらの悪質なアカウントを削除しました。当社では、悪質な行為者と闘い、利用規約を実施するために、自動化されたテクノロジーと調査専門家チームおよび会員からの報告を組み合わせて、当社製品全体で使用しています。私たちは継続的にプロセスを進化・改善し、お客様や会員の皆様が疑わしい活動を報告することを奨励しています。

追加情報

- GitHubユーザーは、利用規定と不正使用とスパムの報告ページでより詳細な情報を得ることができます。

- LinkedInユーザーは、不正利用の特定と報告について、こちらで詳しく知ることができます:スパム、不適切なコンテンツ、悪用されたコンテンツの認識と報告

本レポートでは、「Slow Pisces」がどのようにマルウェアをコーディングの課題の中に隠しているのか、また、この脅威に対するより広い業界への理解を提供することを目的として、同グループのその後のツールについて詳述する

Palo Alto Networksのお客様は、次世代ファイアウォール(アドバンスドURLフィルタリング機能付き)およびアドバンスドDNSセキュリティのサブスクリプションにより、本記事で取り上げた脅威からより確実に保護されます。

情報漏えいの可能性がある場合、または緊急の案件がある場合は、Unit 42インシデント対応チームまでご連絡ください。

テクニカル分析

このキャンペーンは、図1に示す3つのステップに大別される。

Diagram illustrating cybersecurity threats involving PDF lures, GitHub repositories, and a C2 server. It shows: 1) PDF files like job descriptions and question sheets acting as lures, 2) GitHub JavaScript and Python repositories with multiple external APIs, potentially fetching malicious data, and 3) a C2 server configured to send benign data or a malicious payload under certain conditions. Palo Alto Networks and UNIT 42 logos are included.
図1.スローピスケスの「コーディング・チャレンジ」キャンペーンの概要。

ステージ1 - PDFルアー

Slow Piscesは、まずLinkedInでリクルーターになりすまし、潜在的なターゲットに接触し、図2に示すような求人情報を記載した良質のPDFを送信しました。潜在的なターゲットが応募すると、攻撃者は質問シートに概説された深刻度からなるコーディングの課題を提示しました。

Image displaying two documents side by side. On the left is a 'Job Description' for a UX Design Team Coordinator. On the right is a 'Question Sheet' containing technical and general questions related to user experience (UX) design.
図2.良性のPDFルアー。

私たちは、主に暗号通貨分野で、Slow Piscesがこのような誘い文句でいくつかの組織になりすましているのを観測しています。問題シートには、一般的なソフトウェア開発タスクと、以下の図3に示すGitHubリポジトリにリンクする「リアル・プロジェクト」コーディング・チャレンジが含まれている。

Screenshot of a document titled "Coding and Problem-Solving Skills With Real Project." It includes a link to a GitHub repository and outlines a coding task involving Bitcoin and Ethereum exchange rates from API sources. The text requests enhancements to the project by adding more market APIs and improving the network communication in the code.
図3.PDFルアーに含まれる「リアルプロジェクト」コーディング課題。

ステージ2 - GitHubリポジトリ

スロー魚座は、GitHubのリポジトリからプロジェクトとして、いわゆるコードチャレンジをターゲットに提示した。リポジトリには、閲覧や分析のためのアプリケーションなど、オープンソースプロジェクトから転用されたコードが含まれていた:

  • 株式市場データ
  • 欧州サッカーリーグの統計
  • 気象データ
  • 暗号通貨の価格

このグループは主にPythonまたはJavaScriptのプロジェクトを使用しており、ターゲットがフロントエンド開発またはバックエンド開発のどちらに応募したかに応じているようです。また、このキャンペーンではJavaベースのリポジトリも見かけましたが、jCoinと呼ばれる暗号通貨アプリケーションになりすました2つの事例があるだけで、頻度ははるかに低いものでした。

この希少性は、攻撃者がターゲットの好みのプログラミング言語に基づいてオンデマンドでリポジトリを作成した可能性を示唆している。その結果、このグループは、JavaScriptやPythonなど、暗号通貨分野で人気の高い言語をより頻繁に使用していた。同様に、未発見のリポジトリが他のプログラミング言語にも存在する可能性がある。

ステージ3a - Pythonリポジトリ

2024年後半、グループは正規のリポジトリから転用した「Stocks Pattern Analyzer」と題する図4に示すプロジェクトを使用した。

Screenshot of a GitHub repository named "Stocks Pattern Analyzer" showing file structure on the left and README file content on the right explaining how to run the application directly and with Docker.
図4.「Stocks Pattern Analyzer」Pythonリポジトリ。

リポジトリにあるコードのほとんどは良性のものである。ターゲットが質問シートに従ってプロジェクトを実行しようとすると、データは3つのリモートロケーションから取得されます:

  • 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のうち2つはウィキペディアからデータを引っ張ってきている。3つ目のURLはSlow Piscesが管理するドメインを使用している。このパターンは、複数のデータソースを使用し、そのほとんどが正当なものだが、1つは悪意のあるものである。

悪意のあるコマンド&コントロール(C2)サーバーは、正規のソースのフォーマットを模倣するように設定されています。この場合、上記の正規のウィキペディア・ドメインに見られるように、enサブドメインとorgトップレベルドメイン(TLD)を使用します。

YAMLのデシリアライズ

Slow Piscesは、単純にマルウェアを直接リポジトリに置いたり、Pythonの組み込み関数evalやexecを使ってC2サーバーからコードを実行したりすることができる。しかし、これらの手法は手動検査でもアンチウイルスソリューションでも簡単に検出されます。

その代わりに、Slow PiscesはまずC2サーバーが有効なアプリケーションデータで応答することを確認します。例えば、上記のリポジトリはS&P500の企業シンボルのリストを期待しています。C2のURLは最初にこのデータをJSON形式のリストで返信します。

脅威アクターは、IPアドレス、地理的位置、時間、HTTPリクエストヘッダに基づいて、悪意のあるペイロードを確認されたターゲットにのみ送信します。広範なフィッシング・キャンペーンとは対照的に、LinkedInを介してコンタクトを取った個人に焦点を当てることで、グループはキャンペーンの後期段階を厳密に制御し、予想される被害者にのみペイロードを配信することができます。

疑わしいeval関数とexec関数を避けるために、Slow Piscesは図5に示すようにペイロードを実行するためにYAMLのデシリアライズを使用します。

Screenshot of Python code defining a function 'fetch_symbols' which retrieves stock symbols from the S&P 500 using an API call, handles different content types, and processes responses based on their content type. The last line has a section highlighted in a red box.
図5.YAMLデシリアライズを使用したSlow Piscesマルウェアのエントリーポイントを示すPythonコード。

このコードはHTTPS経由でC2サーバーからデータを取得し、Content-Typeレスポンスヘッダをチェックする。ヘッダがJSONデータ(application/json)を示している場合、コードはJSONを解析し、アプリケーションに返す。

レスポンスがYAMLデータ(application/yaml)を示している場合、コードはPyYAMLライブラリのyaml.load()関数を使用してデータを解析します。この関数は本質的に安全ではなく、PyYAMLのドキュメントでは、信頼できない入力に対しては yaml.safe_load()明示的に推奨しています

YAMLは通常、以下の例のようなコンフィギュレーション・ファイルに使われる:

しかしながら、yaml.load() は有効な YAML データだけでなく、任意の Python オブジェクトをシリアライズおよびデシリアライズできます。たとえば、次のPythonコードは0から4の数字を表示します:

このコードをyaml.dump()を使ってシリアライズすると、次のようになる:

最後に、このデータをyaml.load()に渡すと、元のコードが実行されます: range(0, 5)

これは、Pythonリポジトリ用のペイロードや、一般的にYAMLデシリアライズを使用するマルウェアが、組み込みのPython関数を使用する場合、!!python/object/apply:builtinsを含むため、潜在的な検出ポイントを強調します。

表1の以下のステージは、主にメモリ上に存在し、一般的にディスク上にはフットプリントを持たない。コミュニティによる検出と認識を支援するため、私たちはこれらのペイロードをVirusTotalにアップロードしました。YAMLデシリアライズのペイロードは、私たちがRN Stealerで観測したC2トークン形式に基づいて、私たちがRN LoaderとRN Stealerと名付けたマルウェアを実行します。

ステージ SHA256ハッシュ
YAMLデシリアライゼーション・ペイロード 47e997b85ed3f51d2b1d37a6a61ae72185d9ceaf519e2fdb53bf7e761b7bc08f
RNローダー 937c533bddb8bbcd908b62f2bf48e5bc11160505df20fea91d9600d999eafa79
RNスティラー e89bf606fbed8f68127934758726bbb5e68e751427f3bcad3ddf883cb2b50fc7

表1.Pythonリポジトリのペイロード。

Slow PiscesのYAMLデシリアライズペイロードは、被害者のホームディレクトリにPublicフォルダを作成し、そのディレクトリに__init__.pyという名前の新しいファイルを作成することから始まります。埋め込まれたBase64データはデコードされ、次の感染ステージ(RN Loader)を含むこのファイルに書き込まれ、実行されます。

RNローダー

この~/Public/__init__.pyに新しく作成されたRN Loader用のファイルは、実行後にそれ自体を削除し、メモリ上にのみ存在することを保証する。被害者のマシンとオペレーティングシステムに関する基本的な情報を HTTPS 経由で en.stockslab[.]org の同じ C2 に送信し、続いて表 2 にある以下のオプションでコマンドループを実行します。

コード 説明
0 20秒間スリープ
1 送信されたコンテンツをBase64デコードし、Windowsの場合はinit.dll、その他のOSの場合はinitというファイルに保存する。

環境変数 X_DATABASE_NAME に空の文字列を設定する。

ctypes.cdll.LoadLibraryを使用して、ダウンロードしたDLLをロードして実行します。

2 送信されたコンテンツをBase64デコードし、Python組み込みのexecを使って実行する。
3 送信されたコンテンツとパラメータをBase64デコードする。コンテンツは dockerd というファイルに保存され、パラメータは docker-init というファイルに保存される。

dockerd、コマンドライン引数としてdocker-initを与えて、新しいプロセスで実行される。

9 実行を終了する。

表 2.RNローダーのコマンド表。

オプション1と3を使用した表2のコマンドループのペイロードは現在のところ不明であり、特定の条件によってトリガーされる可能性が高い。しかし、私たちはオプション2によって配信されたPythonベースのinfostealerを回収し、このマルウェアをRN Stealerとして追跡しています。

RNスティラー

RN Stealerはまずランダムな被害者IDを生成し、その後C2サーバーとのすべての通信でクッキーとして使用される。その後、C2サーバーに、流出したデータを暗号化するためのXORキーを要求する。

C2サーバーとの通信はHTTPSで行われ、リクエストとレスポンスのタイプを識別するためにBase64エンコードされたトークンが使用される。分析されたペイロードには4つのトークンタイプが含まれる:

  • R0 - XORキーのリクエスト
  • R64 - データの流出
  • R128 - 圧縮データの流出
  • R256 - インフォステア完成

これらのトークンタイプの書式(Rの後に整数のNが続く)は、このペイロードの名前につながった。ペイロードをRN Stealer、その前段をRN Loaderと呼ぶことにする。

私たちは、このRN StealerサンプルのスクリプトをmacOSシステムから回収しました。そのため、脅威の作成者は、以下のようなmacOSデバイス固有の情報を盗むために、このサンプルをカスタマイズしました:

  • 被害者の基本情報ユーザー名、マシン名、アーキテクチャ
  • インストールされているアプリケーション
  • 被害者のホームディレクトリのディレクトリリストとトップレベルの内容
  • macOSシステムに保存された認証情報を保存するlogin.keychain-dbファイル
  • SSHキーの保存
  • AWS、Kubernetes、Googleクラウド用の設定ファイル

RN Stealerが収集したデータは、おそらく永続的なアクセスが必要かどうかを決定する。もしそうであれば、このPythonの感染チェーンには次のようなステップがあると推測できる:

  1. C2サーバーはビーコンを発する犠牲者を未知の基準に照らしてチェックする。有効な被害者はYAMLデシリアライズのペイロードを受け取る。無効な犠牲者は良性のJSONデータを受け取る。
  2. デシリアライズペイロードは、C2サーバーとのコマンドループを確立し、基本的な被害者情報を流出させ、表2のオプションコード2を介してカスタムPythonインフォステーラーを配信します。
  3. infostealerは、より詳細な被害者情報を収集し、攻撃者が継続的なアクセスが必要かどうかを判断するために使用したと思われる。
    1. 継続的なアクセスが必要な場合、C2サーバーはオプションコード1または3を介してペイロードを配信する。
    2. アクセスが不要になると、オプション・コード9がマルウェアの実行を終了し、ペイロードがメモリ上にのみ存在するため、すべてのアクセスを削除する。

ステージ3b - JavaScriptリポジトリ

標的とされた被害者がJavaScriptの役割を申請した場合、代わりに以下の図6の例のような「暗号通貨ダッシュボード」プロジェクトに遭遇するかもしれない。

Screenshot of a GitHub repository named "Cryptocurrency Dashboard," featuring a README.md file displayed. This README includes sections: Features, Installation, Usage, Project Structure, Configuration, Dependencies, and License. It describes the project as an application built with Node.js, Express, and EJS that displays real-time and historical data for various cryptocurrencies.
図6.JavaScriptリポジトリ。

このアプリケーションには、C2と正規のデータソースを含む.envファイルが含まれています:

  • 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サーバーは検証されたターゲットにのみペイロードを配信し、それ以外はバージョン番号で応答します。

このリポジトリは、Embedded JavaScript (EJS)テンプレート・ツールを使用し、C2サーバーからのレスポンスを図7に示すejs.render()関数に渡す。

Screenshot showing a code snippet in JavaScript. It includes a comment and a function call to render a homepage with settings and items per page. res.render is highlighted in a red box.
図7.EJSレンダー関数を使ったSlow Piscesマルウェアのエントリーポイントを示すJavaScriptコード。

yaml.load()の使用と同様に、これもC2サーバーからの任意のコードの実行を隠すためにSlow Piscesが採用している手法の一つであり、この手法はおそらく有効なペイロードを表示したときにのみ明らかになる。

EJSのレンダー関数はさまざまなパラメータを受け付けるが、そのうちのひとつがビューオプションと呼ばれるものである。この中で任意のJavaScriptコードを与え、escapeFunctionキーで実行することができる。

Huliというハンドルネームを持つ台湾の研究者は、CTFの投稿で、この結果どのように任意のコードが実行されるかという技術的な詳細について議論している。しかし、図8のように構造化されたペイロードがejs.render()に渡されると、escapeFunctionに含まれるコードが実行されることは十分に理解できる。

Screenshot of a JavaScript code snippet involving functions with "escapeFunction" highlighted in a red box.
図8.EJSレンダーペイロードの一部。

残念ながら、このペイロードの全容を復元することはできなかった。そのため、ユーザーのホーム・ディレクトリの下に新しいディレクトリ.jqlが作成され、そこにBase64エンコードされたデータを含むhelper.jsというファイルがドロップされると推測するしかない。

インフラ

以下の図9のタイムラインは、2024年2月から2025年2月までのキャンペーンで使用されたC2インフラストラクチャの詳細を、提供されたリポジトリのタイプ(JavaScriptまたはPython)ごとにグループ化したものである。

Timeline of infrastructure tracking the JavaScript command and controls (top, yellow label) and the Python command and controls (bottom, orange label). The timeline starts at the end of Q1 of 2024 and continues to Q2 of 2025.
図9.C2インフラのタイムライン。

前述したように、このキャンペーンのインフラストラクチャのドメインは、apiやcdnのようなサブドメインを頻繁に使用し、合法的なソースの形式を模倣することができます。私たちは、この記事の時点までに、このキャンペーンに関連するインフラを発見しています。

結論

本レポートでは、LinkedIn上でリクルーターになりすまし、暗号通貨分野の開発者をターゲットに悪意のあるコーディングチャレンジを行うSlow Piscesの最新のキャンペーンを取り上げました。JavaScriptリポジトリに対する完全な攻撃チェーンを回収することはできませんでしたが、このキャンペーンのPythonバージョンでは、RN LoaderとRN Stealerと名付けた2つの新しいペイロードが配信されました。

LinkedInとGitHubをこのように利用するのは特殊なことではない。複数の朝鮮民主主義人民共和国系のグループが、Alluring PiscesContagious Interviewといった同様の手口を使っている。

これらのグループには、活動上の重複はない。しかし、これらのキャンペーンが類似した初期感染ベクトルを利用していることは注目に値する。

低速魚座は、運用上のセキュリティにおいて同業他社のキャンペーンとは一線を画している。各段階でのペイロードの受け渡しは厳重に守られ、メモリ上にのみ存在する。そして、このグループの後段ツールは、必要な場合にのみデプロイされる。

特に、このグループは機能を隠すために2つのテクニックを駆使した:

  • YAMLのデシリアライズ
  • EJS escapeFunction

この2つのテクニックは、分析、検出、ハンティングの妨げになる。同様に、暗号通貨分野の比較的新しい、あるいは経験の浅い開発者は、これらのリポジトリを悪意のあるものとして識別することが難しいだろう。

暗号通貨強盗の公的な報告に基づいて、このキャンペーンは非常に成功しているように見え、2025年に持続する可能性が高い。この記事では、YAMLデシリアライゼーションとEJS escapeFunctionペイロードの2つの潜在的な検出機会を取り上げたが、最も効果的な緩和策は、企業と個人のデバイスを厳密に分離することである。これにより、標的型ソーシャル・エンジニアリング・キャンペーンによる企業システムの侵害を防ぐことができます。

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 パイソン
cdn[.]clubinfo[.]io 5.206.227[.]51 2025-01-21 2025-02-19 パイソン
getstockprice[.]info 131.226.2[.]120 2025-01-21 2025-01-23 パイソン
api[.]stockinfo[.]io 136.244.93[.]248 2024-10-30 2024-11-11 パイソン
cdn[.]logoeye[.]net 54.39.83[.]151 2024-10-29 2024-11-03 パイソン
ja[.]wfinance[.]org 195.133.26[.]32 2024-10-12 2024-11-01 パイソン
en[.]stocksindex[.]org 185.236.231[.]224 2024-09-11 2024-10-04 パイソン
cdn[.]jqueryversion[.]net 194.11.226[.]16 2024-08-23 2024-09-23 ジャバスクリプト
en[.]stockslab[.]org 91.103.140[.]191 2024-08-19 2024-09-12 パイソン
update[.]jquerycloud[.]io 192.236.199[.]57 2024-07-03 2024-08-22 ジャバスクリプト
cdn[.]soccerlab[.]io 146.70.124[.]70 2024-08-07 2024-08-21 パイソン
api[.]coinpricehub[.]io 45.141.58[.]40 2024-05-06 2024-08-06 ジャワ
cdn[.]leaguehub[.]net 5.133.9[.]252 2024-07-15 2024-07-21 パイソン
cdn[.]clublogos[.]io 146.19.173[.]29 2024-06-24 2024-07-12 パイソン
api[.]jquery-release[.]com 146.70.125[.]120 2024-06-10 2024-06-28 ジャバスクリプト
cdn[.]logosports[.]net 185.62.58[.]74 2024-05-08 2024-06-23 パイソン
skypredict[.]org 80.82.77[.]80 2024-05-06 2024-06-16 ジャバスクリプト
api[.]bitzone[.]io 192.248.145[.]210 2024-04-25 2024-05-13 パイソン
ウェザーデータハブ[.]org 194.15.112[.]200 2024-04-05 2024-05-03 ジャバスクリプト
api[.]ethzone[.]io 91.234.199[.]90 2024-04-16 2024-04-24 パイソン
api[.]fivebit[.]io 185.216.144[.]41 2024-04-08 2024-04-14 パイソン
ブロックプライス[.]io 91.193.18[.]201 2024-03-15 2024-04-09 ジャバスクリプト
api[.]coinhar[.]io 185.62.58[.]122 2024-03-26 2024-04-09 パイソン
mavenradar[.]com 23.254.230[.]253 2024-02-21 2024-03-26 ジャバスクリプト
indobit[.]io 146.70.88[.]126 2024-03-19 2024-03-20 パイソン
api[.]thaibit[.]io 79.137.248[.]193 2024-03-07 2024-03-09 パイソン
chainanalyser[.]com 38.180.62[.]135 2024-02-23 2024-03-06 ジャバスクリプト

その他のリソース

Enlarged Image