#cmdevio2016 (レポート: B-2) Trend Microのセキュリティコンテストの裏舞台でDockerとAnsibleを使った話

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、虎塚です。

Developers.IO 2016のスポンサー様セッション「Hacker meets Docker:セキュリティコンテスト『Trend Micro CTF』の裏舞台でコンテナをつかった話」をレポートします。

トレンドマイクロ株式会社 セキュリティエキスパート本部の岩田季之様にご講演いただきました。

B-2トレンドマイクロ様のセッション

1. CTF

CTFとは、Capture The Flag (旗の奪い合い) の略で、セキュリティに関する技術や知識を競い合う技術者向けの競技大会。ゲーム感覚でセキュリティ知識を学んだり、セキュリティ技術を試したりできる。有名なセキュリティコンテストに、日本ではSECCON、海外ではアメリカのDEF CONなどがある。

トレンドマイクロ社主催のCTFイベントは、2015年にアジアパシフィックと日本限定で初めて開催した。

CTFの問題形式

Jeopardy形式

Jeopardyとは、アメリカのクイズ番組。クイズのような一問一答が特徴。

  1. 出題者が問題文、ファイル、またはURLを参加者へ渡す
  2. 参加者は1を解析する
  3. 参加者は1からフラグ文字列を見つける
    • 方法は、ファイルの中から探す、リバースエンジニアリングする、デバッガをかける、SQLインジェクションを試すなど
    • フラグを見つけると点数が入る。たくさんフラグを見つけて、点数が高い人が勝利する

Attack & Defense形式

  1. 出題者がサーバのIPアドレスなどを参加者へ渡す
  2. 参加者は1を攻撃して侵入する
  3. サーバからフラグ文字列を見つける、または、サーバに書き込んで乗っ取った証をしめす
  4. ほかのチームからサーバを防御する
    • 方法は、脆弱性を防ぐ、攻撃を防御するなど
    • 最も長い時間サーバを占拠したチームが勝利する

Trend Micro CTF 2015の予選はオンラインでJeopardy形式、決戦はJeopardy形式とAttack & Defense形式の組み合わせでおこなわれた。決戦の様子はYoutubeで生中継された。現在も見ることができる。

Trend Micro CTFのBuild & Deploy

  • 開発環境
    • ローカル環境でVagrant、AnsibleやDockerで問題を作る
    • 作ったものをステージングサーバ(VMware上のDocker)にAnsibleでデプロイする
  • 本番環境
    • 参加者の攻撃を受ける環境なので、ネットワーク的に隔離された場所(VMware上のDocker)に作成する
    • AnsibleのPlaybookやソースファイルをファイルコピーする

Trend Micro CTF Build & Deploy

2. Ansible

Ansibleは、構成管理ツール。サーバ構築を自動化できる。

なぜChefやPuppetでなくAnsibleを選んだか

  • エージェントレス
    • ChefやPuppetはエージェントを管理される側のサーバに入れる必要があるが、Ansibleでは不要
    • PythonとSSHが入っていれば管理できる。(これらはたいていのディストリビューションにデフォルトで入っている)
  • 冪等性
    • 何回実行しても同じ結果が出る。サーバを1回構築した後、同じものをもう一回実行しても大丈夫
    • 単純なスクリプトの場合: 1回目の実行でユーザ追加。2回目の実行では、すでにユーザがいるからエラーになる
    • Ansibleの場合: 2回目以降の実行では、ユーザがいなければ追加するが、すでにいれば何もしない
    • 冪等性を重視して標準モジュールが作られているので、使う側が意識しなくても冪等が保たれる
  • AnsibleのPlaybookはyamlフォーマットで敷居が低い
    • ChefのレシピはもはやRubyスクリプト。Rubyが得意でない人や開発者でない人にとっては敷居が高い

3. CTF x Ansible

なぜCTFでAnsibleを使ったか

  • 構築自動化
    • ローカル、ステージング、本番環境など、同じサーバを複数台作る作業を自動化して、ラクができる
  • 設定状況の確認(冪等性)
    • 何回実行しても大丈夫なので、構築だけでなく確認にも活用できる
    • 設定を間違えた可能性がある時、Playbookをもう一度実行すれば、意図した設定になっているかを確認できる
  • 設定の可視化と再現性
    • Playbookで設定をコード化することで、将来も担当者が同じ環境を作ることができる
    • Playbookを見ると実際の設定内容がわかる。仮想マシンのイメージを使っても同じものを動かすことはできるが、設定内容の可視性は低い
  • セキュリティ(次の項で詳述)

Ansible as Security

Ansibleで設定を自動化/コード化することで、設定ミスを防止できる。ある時点まで正しい設定だったが、いつの間にか誰かが変更してしまった等、意図しない事故が起きることはよくある。Ansibleで設定した「つもり」になっていた状況を防止することで、意図したセキュリティレベルを保つことができる。

4. Docker

ここからは、本セッションのメインのDockerについて。

Dockerは、コンテナを実行・管理するためのプラットフォーム。単にコンテナだけでなく、コンテナをより使いやすくするための周辺ツールを含めてDockerという認識。

仮想マシン vs コンテナ

  • 仮想マシン: ハードウェアを仮想化するので、1つのハードウェアの上にそれぞれ仮想マシンを作って、OSを動かす。
  • コンテナ: OSは共通で、その上にアプリケーションが複数乗って動く。

動かしたい対象は、さまざまなアプリであってOSそのものではない。仮想マシンでは、アプリごとにOSを個別に用意する必要があるため、構築コストが高く、効率が悪い。複数のアプリを動かしたいという用途には、コンテナのほうが合う。そのため、最近のクラウド環境やスケールする環境では、コンテナが好んで使われている。

Docker vs 他のコンテナ

以前からLXCSolaris Containersなど他のコンテナシステムがあるが、なぜDockerが流行っているのか。

  • 使いやすいインターフェース (CLI, API)
    • 比較的簡単に使えるDocker command。単一の共通したコマンドを使える
  • Dockerfile
    • Dockerのコンテナイメージを記述するためのソースファイルのようなもの。1つのシンプルな形式のテキストファイルでコンテナのイメージの中身を記述できる。複雑な設定ファイルが不要でわかりやすい
  • Docker Hub
    • Dockerの公開イメージリポジトリ。完成したDockerイメージをダウンロードして、そのまま、または必要な変更を加えて使うことができる
    • WordPress、Elasticsearch、CentOSなどの著名な製品のオフィシャルリポジトリや、個人のリポジトリが公開されている

5. CTF x Docker

なぜCTFでDockerを使ったか

「使いたかったから」という最大のモチベーションはさておき、次の理由でDockerを採用した。

  • ポータビリティ
    • Dockerが動くところであれば、どこでも同じようにアプリを動かせる
    • 仮想マシンイメージの場合は重量でコピーも大変。Dockerの場合は、ソースとアプリファイルさえあれば、コピーで同じ環境を作ることができる
  • 軽量/復旧が楽
    • スナップショットを取っておけば、動かなくなった時に再起動できる
    • 仮想マシンの場合、OSから起動するので1〜数分かかる
    • Dockerの場合、1プロセス上がるだけなので、秒単位できれいな状態のアプリケーションが動く
  • バージョン管理しやすい
    • Dockerfileによってアプリケーションを管理できる。gitなどで構成管理しやすい
    • セキュリティ (今回Dockerを採用した最大の理由。次の項で詳述)

Docker as Security

Dockerがセキュリティ維持に役立つ部分はいろいろあるが、今回採用に至った大きな理由は、次の3つ。

Docker as Security

  • ファイルシステムの分離
    • コンテナ内のファイルシステムは、ホスト側のファイルシステムと独立している
    • コンテナとホストの/etcは別
  • プロセスの分離
    • これがコンテナのコンテナたる所以。1つのコンテナで動いているプロセスは、他のコンテナで動いているプロセスにも、ホストで動いているプロセスにも、アクセスできない
  • ユーザ権限の制限
    • コンテナのrootとホストのrootは違う。ホストのrootは何でもできてしまうが、コンテナのrootは制限されている
    • コンテナのrootに許可される権限 (右) は、ホストのrootの半分以下
    • 参照: Introduction to Container Security - Dockerの4ページ目
    • コンテナ内でps auxwwコマンドを実行すると、実行中のすべてのプロセスがたかだか10数個とわかる。PIDは小さな番号で、限られた権限で動いている。

その他のDocker採用理由としては、ネットワークの分離やCPU/メモリリソースの制限を実現できることが挙げられる。

CTF x Docker

コンテスト参加者にサーバの脆弱性を突かれてシェルを取られたり、万が一rootに権限昇格されたりしても、コンテナ内では依然として権限を制限した状態を保てるので安心。コンテナ内は無茶苦茶にされても、コンテナの外にまで影響を及ぼすことはできない。

コンテストの決勝ともなるとツワモノが集まってくるので、出題側が意図して残した脆弱性意外にも、意図しない脆弱性を突かれることが往々にしてある。実際、海外のコンテストでは管理・運営サーバのほうを攻撃されて、乗っ取られたことがあった。そのようなことが起きてスコア改竄がおこなわれることを防ぐために有用だった。

Dockerに脆弱性がないかぎりという前提はあるが、Docker使うことで、普通に仮想マシンを使うよりもセキュリティレベルを上げることができる。

実際の利用例

例1: CentOS 6 Apache + PHP + MySQLのWebアプリ

monitを利用して、単一コンテナでWebアプリケーションとDBを両方動かした。本来は、WebアプリケーションとDBで2つコンテナを作り、その間をつなぐのが美しい構成だが、今回は複数コンテナを管理すると煩雑になるのでまとめた。monitがWebサーバとDBサーバを立ち上げる。

例2: mini_httpd + PHP + SQLiteのWebアプリ

必要最低限の実行ファイルしかない状態にした。実行ファイルはすべてstaticリンクさせ、ライブラリが全然インストールされていない状態にした。(lsコマンドもない状態)

Dockerの落とし穴

DockerをCTFで実際に使ってみて、ハマったことについて共有する。

落とし穴1: Docker x iptables

コンテスト参加者からの攻撃にそなえて、DockerコンテナのiptablesではINPUT/OUTPUTとも必要最小限のポートだけ開けて、INPUTの接続数制限もかけていた(hashlimit)。しかし、許可してないはずの通信ができたり、制限レート以上の接続を受けつけたりする事態が起きた。

Dockerコンテナのネットワークでは、デフォルトでdocker0という仮想NICが作成され、ホストとコンテナがブリッジ接続される。各コンテナにはIPアドレスが振られ、Dockerはiptablesを自動で設定する。Dockerは、ホスト宛にきたリクエストをPREROUTINGでNATして、それぞれのコンテナに届ける。

Docker x iptables

今回はiptablesのINPUTとOUTPUTにルールを設定していたが、ホスト宛にきたリクエストは、NAT後にFORWARDされてPOSTROUTINGで各コンテナに届くので意味がなかった。フィルタをするならFORWARDに対してルールを設定しよう。

落とし穴2: Zombieの大量発生

決勝でAttack & Defenseをしている最中に、Zombieプロセスが千〜万単位で発生し、メモリを使い果たして新しいプロセスが生成されなくなった。

サーバに侵入成功したあるチームが、ほかのチームを妨害するために、プロセスをkillするスクリプトをループで回していた。このスクリプトが親プロセスをもkillして、子プロセスが孤児化していた。

ふつうのOSなら親プロセスが死んだ場合に、initが孤児プロセスを回収してくれるが、Dockerコンテナにはinitがない。そのため、孤児が回収されずにZombieプロセスが大量発生して、リソースが解放されない状態になってしまった。Dockerの特長であるプロセス空間の分離が逆効果になった。

Zombie対策としては、コンテナ用のinitを使うこと。

落とし穴3: 仮想マシンが立ち上がらない

上のZombie事件の後、仮想マシンをOSごとリセットした。すると、コンテナが起動直後に終了するようになってしまった。

原因は、コンテナ内にmonitのpidファイルが残っていたため。Dockerで最初に動くプロセスのpidは常に1。起動時に、pid 1のプロセスがすでに存在する状態だったため、もう動かなくていいと判断して、立ち上がらなくなっていた。

これには、コンテナ内のpidファイルを削除することで対処できる。が、本番ではコンテナごと削除して再作成した。

まとめ

  • Dockerの利用には利便性・効率性だけでなく、セキュリティにも一定の効果がある
    • もちろんDockerだけで大丈夫というわけではないが、ある程度のセキュリティ向上を見込める
  • 慣れないツールはいろいろハマる

Q & A

会場からの質問にご回答いただきました。

  • Q. 競技中にDockerコンテナの監視はどのようにされていたんですか?
  • A. Dockerコンテナのパフォーマンス値はコンテナの外から見えるので、運営側はホストの外からふつうに見ていました。

  • Q. 今回の発表を聴いてCTFに興味をもった人がとっかかりとして取り組めることは何でしょうか?

  • A. オンライン予選にはだれでも参加できます。また、常にCTFの問題を公開しているWebサイトがあります。SECCONに関わっているメンバーが、セキュリティコンテストについての本を出しているので、見ていただくのもよいかもしれません。

おわりに

Deep Securityをはじめとするセキュリティ製品の開発元であるトレンドマイクロ社の方が、セキュリティを考慮してDockerを採用されたというお話はとても興味深いものでした。今回の事例はセキュリティコンテストという特殊な用途ですが、Dockerがセキュリティ面で有利な点があることがよく理解できました。

今後は、起動速度や可搬性に加えて、セキュリティという軸からも、コンテナを採用する場面が増えるかもしれません。その時にまた参考にさせていただきたい発表内容でした。岩田様、ご講演ありがとうございました。

それでは、また。