Sysdig Threat Research Teamによると、ある脅威アクターがmarimoに存在する認証前リモートコード実行(RCE)の重大な脆弱性を悪用し、AWS認証情報を窃取したうえで、AWS Secrets ManagerからSSH秘密鍵を取得し、わずか8秒で踏み台ホストへの認証を完了させたことが判明しました。
CVE-2026-39987として追跡されているこの脆弱性は、marimoバージョン0.20.4までに影響し、バージョン0.23.0で修正されています。
Hacking& Cracking
問題の根本原因は/terminal/ws WebSocketエンドポイントにあります。このエンドポイントは対話型の疑似端末を公開していましたが、他のWebSocketルートに適用されている認証検証が適用されていませんでした。
このエンドポイントにアクセスできる攻撃者は、いかなる認証情報も必要とせずにmarimoプロセスのユーザー権限でシェルを取得できてしまいます。
MarimoのRCE脆弱性
Sysdigの観測によると、攻撃者はUTC18:57:22に新規のWebSocketセッションを開始しました。そのわずか4秒後には、アプリケーションのRedisバックエンドに保存されていたAWS認証情報を取得しています。
そして18:57:30までに、この攻撃者はAWS Secrets Managerから抽出したSSH秘密鍵を使い、インターネットからアクセス可能な踏み台ホストへの認証を完了させました。
研究者たちは、この急速な侵入の進行をAIエージェントによるものとは結論付けていません。むしろ、この攻撃者は以前のセッションで約4時間をかけ、独自のPythonツールキットの構築とデバッグに費やしていたことを指摘しています。
ツールキットが/tmp/ディレクトリに配置された後は、認証情報の復元、Secrets Managerへのアクセス、SSH鍵の抽出、踏み台ホストへの認証といった一連のタスクが、単一のバックグラウンドPython実行によって自動化されていました。
9時間に及ぶ侵入活動の中で、攻撃者は850個を超える対話型コマンドを実行しました。これらのコマンドには、ローカルネットワークの探索、AWS認証情報の検証、Secrets Manager APIの呼び出し、EC2インスタンスの探索、そしてリバースシェル用インフラの準備などが含まれていました。
攻撃者は2つの異なるAWS認証情報の取得経路を利用していました。1つ目の認証情報は、侵害されたホスト上の環境変数または認証情報ファイルから収集されたものです。
一方、2つ目の認証情報は、アプリケーションが保存していた認証情報の値に対するRedis検索を通じて取得されていました。CloudTrailのログによると、これらの認証情報はそれぞれ異なるIAMユーザーに属していたことが分かっており、最初の認証情報セットで目的のシークレットを暴くことができなかったため、攻撃者が繰り返しIDを切り替えていたことがうかがえます。
攻撃者が使用した独自スクリプトは、Boto3ライブラリを利用して`secretsmanager:GetSecretValue`を呼び出しており、複数のAWSリージーンにまたがるフォールバック試行も含まれていました。取得された秘密鍵のデータは、踏み台ホストに対して再利用される前に、パーミッション0600の設定で`/tmp/bastion_key`に保存されていました。
さらに、この攻撃者はEC2 Instance Connectを通じた別の永続化手法も試みていました。AWSのログには、`DescribeInstances`、`DescribeKeyPairs`、`DescribeInstanceInformation`に対する拒否済みリクエストが記録されており、その後にはプレースホルダーのインスタンスID「i-0000000000000000」を対象とした`SendSSHPublicKey`リクエストがブロックされた記録も残っています。この一連の挙動は、信頼性の高い振る舞い検知シグナルとして利用できる可能性があります。
IOC(侵害指標)一覧
| 指標の種類 | 値 | 役割・検知の文脈 |
|---|---|---|
| 送信元IPアドレス | 172.236.12[.]17 |
対話型の/terminal/ws WebSocketセッション。AS63949 Akamai Connected Cloud/Linode |
| C2/中継IPアドレス | 45.79.187[.]72 |
攻撃者が制御するVPSで、`nc -lvp 4444`によるコールバックリスナーとして使用 |
| 脆弱なエンドポイント | /terminal/ws |
未認証のmarimo WebSocket端末エンドポイント |
| 設置されたファイル | /tmp/chain.py、/tmp/full_chain.py |
Base64デコードされたPython自動化スクリプト |
| SSH鍵のパス | /tmp/bastion_key |
Secrets Managerから取得され、パーミッション0600で保存された秘密鍵 |
| ログの痕跡 | /tmp/chain.log、/tmp/chain_output.txt、/tmp/callback.log |
チェーン実行とリスナー活動に関連する出力ファイル |
| AWS API | secretsmanager:GetSecretValue |
SSHピボットに先立つシークレットの取得 |
| AWS APIのパターン | DescribeInstances → 拒否、DescribeKeyPairs → 拒否、DescribeInstanceInformation → 拒否、SendSSHPublicKey |
失敗したEC2 Instance Connect自動化シーケンス |
| コマンドパターン | base64 -d > /tmp/<name>.pyに続くnohup python3 |
スクリプトの配置とバックグラウンド実行の挙動 |
注記: IPアドレスとドメインは、誤って名前解決やハイパーリンク化されるのを防ぐため、意図的に無害化表記(defang、例: [.])にしています。再度有効な表記に戻す作業は、MISP、VirusTotal、またはお使いのSIEMなど、管理された脅威インテリジェンスプラットフォーム内でのみ行ってください。
各組織は、marimoを直ちにバージョン0.23.0以降にアップグレードし、ノートブックサービスへのネットワークアクセスを制限する必要があります。防御担当者は、/terminal/wsへの未認証接続、AWS Secrets Managerにアクセスする不審なPythonプロセス、/tmp配下に書き込まれたSSH秘密鍵、そしてポート4444への未承認ホストへの発信接続などを重点的に監視すべきです。
CloudTrailによる検知においては、攻撃者の操作の癖そのものよりも、攻撃の連鎖パターンを優先して見るべきです。具体的には、侵害されたワークロードのIDによるSecrets Managerの呼び出しに続いて、SSH認証、不審なEC2 Instance Connectの活動、あるいは未承認先への発信コールバック通信が発生していないかを確認する必要があります。
SOCを最新の状態に保ち、活動中のマルウェアやフィッシングの発生から24時間以内に把握しましょう。 早期検知でインシデントを未然に防ぐANYRUNをぜひお試しください。
翻訳元: https://gbhackers.com/marimo-rce-flaw/