ytooyamaのブログ

サーバ構築とか、仕事で発見したこととか、趣味のこととかを書いています。

「Dockerのサーバーを狙うマルウェア2種を確認--トレンドマイクロ」の記事を読んで

SNSでシェアされてきたので、早速確認しました。

japan.zdnet.com

もう少しくわしい話が以下で公開されていました。

unit42.paloaltonetworks.jp

ちなみにこの件は最近報告された問題ではなく、結構前から言われていたことです。設定の不備から外部から無認証でコンテナーを実行されてマイニングに使われるみたいな話です。

jp.cointelegraph.com

Dockerやべえ。早くほかのコンテナランタイムにしないと ...ではなく、「お前のDockerの設定、やべえから」...という話なのです。

早速確認してみました。

実験開始

最初の記事によると、2375/tcpポートが狙われる対象だそうです。そんなポート、普通は空いていたっけ? 最後の記事によると、2376/tcp、2377/tcp、4243/tcpなんかもスキャン対象のポートみたいですね。

ポート番号「2375/tcp」で調べたら、このドキュメントを見つけました。

docs.docker.jp

「Docker Remote API」を使ってリモートのDockerでコンテナーを実行する事ができる機能ですね。便利だったので私も一時期使っていました。 ちなみにこの設定はデフォルトでは無効のはずです。

[root@docker-demo ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since 火 2020-08-25 10:42:16 JST; 11min ago
     Docs: https://docs.docker.com
 Main PID: 2958 (dockerd)
    Tasks: 8
   Memory: 40.3M
   CGroup: /system.slice/docker.service
           └─2958 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

[root@docker-demo ~]# ss -natu |egrep "2375|2376"
[root@docker-demo ~]# 

systemctl status docker コマンドなどを実行して、dockerdのオプションに問題のあるような設定が書かれていない場合はおそらく問題ないです。

しかし「Docker Remote API」とかで検索してブログの記事の方法で設定を書き換えてポートまで開放してしまった場合、設定が不適切であると悪用される可能性があります。 以下に実施しては本当にだめな設定例を書きます。絶対にDockerホストでこのような設定はしないでください。

# vi /usr/lib/systemd/system/docker.service
...
[Service]
...
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock

# systemctl daemon-reload
# systemctl restart docker

# firewall-cmd --add-port=2375/tcp --zone=public --permanent
# firewall-cmd --reload

0.0.0.0:2375で待ち受けするように設定し、かつpublic zoneでポート2375を開放しています。 かなりセキュリティ的にだめな設定例です。

例示したような設定を行うと、リモートからコンテナー基盤へのアクセスが無認証で行えてしまいます(下記例はデーモンとしてNGINXサーバーを起動した例)。

$ docker -H tcp://192.168.56.126:2375 container run --name=nginx1 -d -p 8080:80 -it nginx:alpine
Unable to find image 'nginx:alpine' locally
Trying to pull repository docker.io/library/nginx ... 
alpine: Pulling from docker.io/library/nginx
df20fa9351a1: Pull complete 
3db268b1fe8f: Pull complete 
f682f0660e7a: Pull complete 
7eb0e8838bc0: Pull complete 
e8bf1226cc17: Pull complete 
Digest: sha256:a97eb9ecc708c8aa715ccfb5e9338f5456e4b65575daf304f108301f3b497314
Status: Downloaded newer image for nginx:alpine
c561de3a7819fedb3c69285a790e6181fb24f7945bd2b987931dba7487291f5c

こんな脆弱な設定のDockerホストがパブリッククラウド上で動いていて、かつ固定のグローバルIPアドレスなんかが割り当てられてポートも空いていたら、あっという間に悪用されそうですね。

アクセスを許可するホストをファイアウォールなどで絞ったりすればいくらか軽減できるかもしれませんが、この用途ならKubernetesやDocker swarmなどでコンテナクラスターを構築して使うほうが良いと思います。あとはむやみに外部に開放しないということも...。

どうしても「Docker Remote API」を使わなければならない場合は次を参考に、利用に証明書が必要な構成を取るべきでしょう。

docs.docker.com

ここも目を通すべきでしょう。

docs.docker.com

Dockerを使っている場合、Kubernetesのようなコンテナー基盤のエンジンとしてDockerを使っている場合は、一度Dockerの設定を確認したほうが良いと思います。Dockerの基本的な設定/etc/docker/daemon.json とか、 /etc/default/docker/etc/sysconfig/docker などに記述されていると思いますが、ディストリビューションやバージョンによって別のパスに書いている場合もあるので、 ps aux|grep docker などで確認するなど、よく調べたほうが良いと思います。

また、ホストに不審なコンテナーやシェルスクリプトがないかも確認したほうが良いと思います。

このブログサイトはJavaScriptを使っていますが、読み込んでいるJavaScriptは全てはてなが提供しているものであり、筆者が設置しているものではありません。