今更だけどDockerコンテナの脆弱性をRancher経由で利用されroot権を渡してしまった話


「脆弱性」というほど大げさなものではなく、Dockerが普及した頃から注意喚起されていた内容ですが、仲間内の環境ということもあり油断していました。今回は戒めの意味も込めて記事を書かせていただきます。

使用していた環境

  • VPS(2コア/8GB Ubuntu 18.04) *2台
    • VPS1台は Docker + Kubernetes を管理するためRancherマスターとして使用
    • 残りの1台はRancher管理下のホストとしてKubernetesを構成…デプロイ用
  • 権限の状況(どちらもログインできるのは私のみ)
    • VPS/Rancherマスター…sudo, docker グループに所属するユーザー1個。公開鍵でのみssh可能
    • VPS/ホスト…sudo, docker グループに所属するユーザー1個。公開鍵でのみssh可能
  • 環境を使用する人
    • 趣味で一緒にコードを書いている友達
      • 環境構築が面倒なのでRancherの構築などは私に投げている
      • こいつが今回の犯人

脆弱性への攻撃内容

dockerコンテナをrunする際に「-v」オプションでVPSマシンの "/" と、コンテナの指定ディレクトリを関連付け、 "chroot"を実行。
コンテナ上からVPSマシンに対してroot権限であらゆる書き換えを実行。(sshd_config 書き換えなど)

情報はこちらを参考にさせていただきました。
- Don't expose the Docker socket (not even to a container)
- コンテナ・セキュリティ入門 と Kubernetes(qiita記事)

上記をdocker コマンド で実行した場合の手順 ※説明のために記載します。実際に実行はしないでください。

docker run -it -v /:/root debian /bin/bash
#ローカルマシンのロートディレクトリ"/"をdebianコンテナの"/root"ディレクトリと同期させた状態で実行

root@{コンテナID}:/# cat /etc/hostname
{コンテナID}
#コンテナ上でbashを実行していますので、当然コンテナの名前が返ってきます。

root@{コンテナID}:/# chroot /root
:# /bin/bash
#ローカルマシンの"/"と関連付けている"/root"に対してchrootを実行して"/"の操作が可能に。試しにbashを起動してみる..

root@{コンテナID}:/# cat /etc/hostname
{ローカルマシンのホスト名}
#同じコマンドを実行しましたが、今度はローカルマシンの名前が出てきました。あとはやりたい放題です。

root@{コンテナID}:/# vi /etc/ssh/sshd_config
root@{コンテナID}:/# ps aux
root@{コンテナID}:/# lsof -i -P
#などなど..

Rancher で実行された内容

  1. adminユーザー(私)が新規ユーザー(犯人)を作成。
  2. 作成したユーザーに最低限の権利を付与。
  3. 新規ユーザーがログイン。
  4. プロジェクトの作成権限があるクラスターでコンテナを作成。
  5. 以降は上記のdockerコマンド実行内容と同様。

以下Rancherの操作画面を使って説明いたします。

1.adminユーザー(私)が新規ユーザー(犯人)を作成。

adminでログインし、「グローバル」タブの「ユーザー」を選択しユーザーを追加する。

ユーザーの内容は以下で作りました。
ユーザー名: waruihito
パスワード: waruihito
表示名: waruihito
グローバル権限: 一般ユーザー

2.作成したユーザーに最低限の権利を付与。

クラスターのメンバーにも新規ユーザーを追加。(今回のクラスタ名は「sandbox」)
今回は最低限の権限として「Create Project」のみを付与します。

3.新規ユーザーでログイン。

作成したユーザーでログインし直すと、権限が振られているクラスターのみが表示されます。

「Create Project」権限を持っているので、新規プロジェクト「warudakumi」を作成します。

4.クラスターでコンテナを作成。

先程の「warudakumi」プロジェクトで、「ワークロード」から乗っ取り用のコンテナをデプロイしていきます。

5.以降は上記のdockerコマンド実行内容と同様。

ボリュームにノード上の "/" パスを指定します。

作成したコンテナ(ポッド)でシェルを実行します。(Rancherではプルダウンから選択して起動できます。)

コマンドを実行して乗っ取りができました。

学んだこと

Docker単体で運用するときには結構気を使っている部分ですし、公式のリファレンスにも「ここに気をつけて!」みたいな文言は書いてあります。
しかしk8sやRancherなどで運用する際には「それは知ってて当然だよね?」という暗黙のルールのもと構築をしてしまうことで、このような初歩的な脆弱性を疲れることになりました。(いや口で言ってくれたら分かるよ?わざわざsshd_config書き換える必要ある?印象には残ったけどね!)

基本大事!効率的にするためであって、横着してもいいわけではないということだと思います。