Marsの5εcur1ty備忘録

不定期的にCTF、脆弱性検証、バグバウンティレポート分析など、情報セキュリティを中心とした技術ブログを更新します。

Dockerを使ってみた(Kali Linux)

こんにちは、Marsです。

最近、Dockerというものが非常に流行っていると多くの方がご存知だと思いますが、
この記事では、Dockerについて簡単にご紹介し、インストール手法について紹介したいと思います。

まず、Dockerとは何でしょうか。

Wikipediaでは、
「Docker(ドッカー[2])はコンテナ型の仮想化環境を提供するオープンソースソフトウェアである[3]。VMware製品などの完全仮想化を行うハイパーバイザ型製品と比べて、ディスク使用量は少なく、仮想環境 (インスタンス) 作成や起動は速く、性能劣化がほとんどないという利点を持つ。」
と言っています。

まずは、コンテナ型、ハイパーバイザについて説明しながら、Dockerの仕組みをざっと説明します。
知っている方は適宜読み飛ばしてください。(笑)

  • コンテナとハイパーバイザ
    f:id:z773733850:20190531225618p:plain

    コンテナとは、これです笑

ふざけんな!と言われるでしょうけど、こういうコンテナをたくさん積み上げた状況を考えましょう。
f:id:z773733850:20190531225848p:plain

それぞれのコンテナの中には木材、プラスチック材、飲料水、石けんなど、いろいろなものがあるとしましょう。

こうしていろいろな製品、材料の容器として使われるのがコンテナです。

ではここでのコンテナ型とは何かというと、現実世界ではコンテナとは同じようなもので、さまざまなプログラミングコードの容器として使われます。

イメージとしては、こんな感じです。
f:id:z773733850:20190531230745p:plain
Image Resource:
https://www.docker.com/resources/what-container

一つのアプリケーションをコンテナ化して使います。公式では、このように解釈されています。
A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.

コンテナは、ソフトウェアの一つの標準的なユニットとして、コードおよびそれに依存するものをパックすることによって、実行が早くて信頼できる環境で動作できることが実現されます。
Reference:
https://www.docker.com/resources/what-container

コンテナ化されたアプリケーションは、仮想マシンで動くアプリケーションと比べ、実行が早い仕組みになっています。
その理由は単純に、仮想マシンでのアプリケーションを動かすには、基盤としてさらにハイパーバイザ、OSが必要だからです。

f:id:z773733850:20190531232831p:plain

Image Resource:
https://cn.teldevice.co.jp/column/10509/

インフラ環境の上にホストOSがあって(今使っているパソコンのOS)、その上にハイパーバイザ(仮想マシンで仮想化を行う制御プログラム)を載せて、さらに仮想マシンにOSをインストールしてはじめてアプリケーションを実行することができます。

つまりホストマシンは、仮想マシンの制御プログラム、仮想OS、アプリケーションを同時に実行しなければなりません。

それに対して、Dockerは、自分のパソコンのOSにDockerエンジンを使えばコンテナ化されたアプリケーションを実行することができるので、仮想マシンと比べて断然CPUとメモリの使用率が少なくて自然にアプリケーションの実行が早いのです。

さて、Dockerのインストールに入ります。こちらの環境はKali linuxを使用しています。

  • Step 0:

パッケージリストを更新する。

sudo apt-get update

  • Step 1:

もし古いバージョンのDockerをインストールしていれば、以下のコマンドでアンインストールすることができます。

sudo apt-get remove docker docker-engine docker.io

  • Step 2:

インストール。

sudo apt-get install docker-ce

  • Step 3:

インストールが成功しているかどうかを確認します。

docker run hello-world

インストールが成功して、Dockerが使用可能の状態であれば、以下のメッセージが表示されるはずです。

Hello from Docker!
This message shows that your installation appears to be working correctly.

  • Step 4:

Dockerエンジンは、Docker本体ともいえる、コンテナ・イメージの管理・実行を行うツールです。
つまり、Dockerを使うには、イメージが必要です。そのイメージとは、Docker用のとある種類のOSのイメージです。
例えば、centosのイメージを使用したければ、以下のコマンドを実行すれば良いです。

docker pull centos

実際にわざわざイメージをインストールせず、dockerにイメージの名前(例えばcentos)を指定してDockerを起動をすれば、
そのイメージが存在しない場合は自動的にイメージファイルをインストールしてからDockerを起動します。

  • Step 5

Dockerを起動します。

docker run -i -t ubuntu /bin/bash

起動が成功すれば、Dockerで制御する仮想システムを使用できます。

また、ポート番号を指定して実行したい場合は、 以下のようにコマンドを実行します。

docker run -p 8080:80 nginx

では、仮に今Dockerfileが与えられて、Dockerにサーバのように機能にてもらいたいとしましょう。

f:id:z773733850:20190601005623p:plain

ここでは、2019年のHarekazeCTFのソースコードを例に説明します。

https://github.com/TeamHarekaze/HarekazeCTF2019-challenges/tree/master/baby_rop/server

Dockerfileの中身:
f:id:z773733850:20190601075106p:plain

Docker内にNetcatサーバを立てて、自分のパソコンのOSから接続したいです。netcatを使用できるようにするまでは、筆者はかなり苦労しました。
Dockerfileの設定として、ubuntuのバージョン16.04がベースとなっています。しかし、ubuntuの中にはnetcatがデフォルトのツールとして入っていません。

そこで、Dockerfileの5行目の一番後ろに\を入れて、6行目を以下のように追加します。

&& apt-get install netcat-traditional

f:id:z773733850:20190601080124p:plain

この状態でDockerイメージをビルドします。

$ docker build -t babyrop102 .

(注意:一番後ろに点(.)を入れないとエラーが出る)

好きな未割り当てのポート番号でDockerイメージを起動します。

docker run -p 6666:6666 -t babyrop102 nc -l -p 6666 -e /home/babyrop/babyrop

(注釈:
docker run -p 6666:6666 -t babyrop102 nc -l -p 6666 -e /home/babyrop/babyrop
の前半部分「docker run -p 6666:6666 -t babyrop102」は、babyrop102という名前のDockerイメージをローカルホスト及び外部ホストともにポート6666で実行することを意味します。後半部分にbabyrop102という環境の内部で実行したいコマンドをくっつければDockerイメージbabyrop102の内部でコマンドを実行することができます。
つまり、 babyrop102という名前のDockerイメージをローカルホスト及び外部ホストともにポート6666で、「nc -l -p 6666 -e /home/babyrop/babyrop」というコマンド実行する、ということです。
)

いざ接続!

nc localhost 6666
What's your name? a
Welcome to the Pwn World, a!

CTFの環境を再現することができました。
一夜漬けする甲斐があった><

ちなみに、先ほど作ったDockerのイメージファイルは、/var/lib/docker/image/overlay2/imagedb/content/sha256の下に保存されています。それを共有することで、環境構築時間ほぼ0で、同じファイルを同じ環境で実行することができます。ファイルのハッシュ値は、docker imagesで確認すると良いでしょう。

また、より簡単に実行する方法としてdocker-composeを使う方法があります。

この方法は、dockerfileを使わず、docker-compose.ymlファイルを設定ファイルとして使います。

もちろんDockerfileもdocker-composeも、自分で書かなければいけません。今回はDockerfileが提供されているので、それを使いました。

docker-composeの使用方法の手順の詳細は、公式webページに書いています。↓

Get started with Docker Compose | Docker Documentation

  • 追記: エラー解消:

Error1:
f:id:z773733850:20190612205952p:plain

解決法:
systemctl start docker
f:id:z773733850:20190612210104p:plain

  • 参考:

qiita.com

https://knowledge.sakura.ad.jp/13265/

Copyright Mars 2019