はじめに
本稿では、Pentester Academyが提供する「Attack Defense」の無料ハンズオン(Free Labs)のうち、「System Backdoor」に注目します。
演習に関する手順のみならず、その背景にあるDocker技術について補足を行っています。
用語解説
Dockerのフォレンジックを理解する上で、そのエコシステムを抑えておくことが重要です。インシデント発生時には、これらエコシステムを構成するコンポーネントを調査することで、一連のイベントを明らかにすることができます。
用語 | 概要 |
---|---|
Docker イメージ(Image) | コード、バイナリ、ランタイム、依存関係、設定ファイルなどアプリケーションの実行に必要なもの一式をまとめたものです。 |
Docker コンテナ(Container) | Dockerイメージを元に作成される仮想環境のこと。コンテナで動作しているプロセスは、ホストと他のコンテナから隔離(isolate)し続けるために、複数のカプセル化する機能をプロセスに対して追加します。 |
レイヤー | コンテナを作成すると変更可能なレイヤーが新しく作成され、その上でプロセスが動作します。コンテナに対して新たに加えられたり修正されたりしたデータは、すべて書き込みレイヤーに保存されます。 コンテナが削除されると、その書き込みレイヤーも同じく削除されます。 |
チェックポイント | 実行中のコンテナ状態(メモリ情報など)をチェックポイントで固定できます。dumpにより、ディスクへ書き出すことも可能です。 |
リストア | 書き出した情報を読み込み、コンテナを実行することが可能です。 |
ネットワーク | Dockerでは、1コンテナでは1プロセスを動かす設計です。複数のプロセスを協調して動作させる場合、ソケットではなく、ネットワークで通信を行うことが推奨されています。 |
「Docker イメージ」、「Docker コンテナ」は単に「イメージ」、「コンテナ」と呼ぶことが多いです。
ケーススタディ
共通する基本列挙
さまざまなDockerフォレンジックケースおいて共通する、基本的な列挙事項を確認します。
Step 1: 実行中のコンテナ一覧を確認
まず、実行中のコンテナ一覧を確認します。
Command: docker ps
オプション
名前/省略形 | 説明 |
---|---|
--all , -a | コンテナすべてを表示します。(デフォルトは実行中コンテナのみ。) |
root@localhost:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e5813268132b lamp-wordpress "./run.sh" 6 minutes ago Up 6 minutes 80/tcp wordpress
root@localhost:~#
上書きされたアーティファクトの復元
Dockerイメージから上書きされたアーティファクトの復元。実行中のDockerコンテナに加えられた変更を分析します。
Step 1: 変更履歴の概要を確認する
Command: docker history
オプション
名前/省略形 | 説明 |
---|---|
--no-trunc | 詳細出力を行います。 |
student@localhost:~$ docker history --no-trunc ubuntuderived
IMAGE CREATED CREATED BY SIZE COMMENT
sha256:1b0b3bfeee1b5e1ab7842c7721725681df978c9e886ad3f279dbdb04a141d84c 2 years ago /bin/sh -c chmod +x /bin/bash 1.11MB
<missing> 2 years ago /bin/sh -c echo "Overwritten" > /root/flag 12B
<missing> 2 years ago /bin/sh -c #(nop) WORKDIR /root 0B
<missing> 2 years ago /bin/sh -c md5sum /bin/bash > /root/flag 44B
<missing> 2 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 years ago /bin/sh -c mkdir -p /run/systemd && echo 'docker' > /run/systemd/container 7B
<missing> 2 years ago /bin/sh -c set -xe && echo '#!/bin/sh' > /usr/sbin/policy-rc.d && echo 'exit 101' >> /usr/sbin/policy-rc.d && chmod +x /usr/sbin/policy-rc.d && dpkg-divert --local --rename --add /sbin/initctl && cp -a /usr/sbin/policy-rc.d /sbin/initctl && sed -i 's/^exit.*/exit 0/' /sbin/initctl && echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean && echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests 745B
<missing> 2 years ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 987kB
<missing> 2 years ago /bin/sh -c #(nop) ADD file:a48a5dc1b9dbfc632f6cf86fe27b770b63f07a115c98c4465dc184e303a4efa1 in / 63.2MB
student@localhost:~$
...
Step 2: Dockerイメージをエクスポートする
Command: docker save
student@localhost:~$ docker save ubuntuderived > image.tar
student@localhost:~$ ls -l
total 66148
-rw-rw-r-- 1 student student 67731968 Jan 28 22:19 image.tar
Step 3: レイヤーの順序についてmanifest.jsonファイルを確認する
Command: cat manifest.json | python -m json.tool
image.tar
を展開する
student@localhost:~$ tar -xf image.tar
student@localhost:~$ ls -l
total 66188
drwxr-xr-x 2 student student 4096 Dec 5 2019 08de39d1ac185319b20c3ad53883b5c21200fab056074ac5d1d442faff04918c
-rw-r--r-- 1 student student 4017 Dec 5 2019 1b0b3bfeee1b5e1ab7842c7721725681df978c9e886ad3f279dbdb04a141d84c.json
drwxr-xr-x 2 student student 4096 Dec 5 2019 27a911bb510bf1e9458437f0f44216fd38fd08c462ed7aa026d91aab8c054e54
drwxr-xr-x 2 student student 4096 Dec 5 2019 b560a3d372ba4276e6b07e827f1ec5a8d019936d168528eb4546e66283093678
drwxr-xr-x 2 student student 4096 Dec 5 2019 b7a6351ad136b46a550495d4048d63458557138c16303bf718bb7b41580264c6
drwxr-xr-x 2 student student 4096 Dec 5 2019 cc59b0ca1cf21d77c81a98138703008daa167b1ab1a115849d498dba64e738dd
drwxr-xr-x 2 student student 4096 Dec 5 2019 d80735acaa72040a0a98ca3ae6891f9abb4e2f5d627b4099c4fefdc3ce1e696e
drwxr-xr-x 2 student student 4096 Dec 5 2019 e2b070f4dd10244735bfe0eb7a976791c90ab2f687177acd2b8b6eab481f6b0a
-rw-rw-r-- 1 student student 67731968 Jan 28 22:19 image.tar
-rw-r--r-- 1 student student 671 Jan 1 1970 manifest.json
-rw-r--r-- 1 student student 96 Jan 1 1970 repositories
manifest.json
ファイルを確認する
student@localhost:~$ cat manifest.json | python -m json.tool
[
{
"Config": "1b0b3bfeee1b5e1ab7842c7721725681df978c9e886ad3f279dbdb04a141d84c.json",
"Layers": [
"cc59b0ca1cf21d77c81a98138703008daa167b1ab1a115849d498dba64e738dd/layer.tar",
"27a911bb510bf1e9458437f0f44216fd38fd08c462ed7aa026d91aab8c054e54/layer.tar",
"d80735acaa72040a0a98ca3ae6891f9abb4e2f5d627b4099c4fefdc3ce1e696e/layer.tar",
"e2b070f4dd10244735bfe0eb7a976791c90ab2f687177acd2b8b6eab481f6b0a/layer.tar",
"08de39d1ac185319b20c3ad53883b5c21200fab056074ac5d1d442faff04918c/layer.tar",
"b560a3d372ba4276e6b07e827f1ec5a8d019936d168528eb4546e66283093678/layer.tar",
"b7a6351ad136b46a550495d4048d63458557138c16303bf718bb7b41580264c6/layer.tar"
],
"RepoTags": [
"ubuntuderived:latest"
]
}
]
Step 4: 上書きされる前のレイヤーについて確認する
実行中のコンテナに加えられた変更を特定する
「System Backdoor」のシナリオでは実行中の WordPress Docker コンテナに侵害の疑いが示されています。このような場合、どのようなステップで調査を行っていくべきなのか、確認します。
Step 1: コンテナのファイルシステム上にあるファイルやディレクトリの変更箇所を確認
コンテナのファイルシステム内にて、コンテナが生成された以降に、変更されているファイルやディレクトリの一覧を確認します。
Command: docker diff
変更内容は次の三種類が示されます。
シンボル | 内容説明 |
---|---|
A |
ファイルまたはディレクトリの追加 |
D |
ファイルまたはディレクトリの削除 |
C |
ファイルまたはディレクトリの変更 |
root@localhost:~# docker diff wordpress
C /run
A /run/supervisor.sock
C /run/apache2
C /run/apache2/apache2.pid
C /run/mysqld
C /run/mysqld/mysqld.pid
A /run/mysqld/mysqld.sock
C /run/supervisord.pid
C /var
...
A /var/log/supervisor/mysqld-stdout---supervisor-9K_Z6Y.log
D /var/log/supervisor/apache2-stdout---supervisor-70UbBd.log
D /var/log/supervisor/mysqld-stderr---supervisor-qMyeIi.log
D /var/log/supervisor/mysqld-stdout---supervisor-vIhK7D.log
D /var/log/supervisor/apache2-stderr---supervisor-MMCU08.log
C /etc
C /etc/shadow
C /etc/php5
C /etc/php5/apache2
C /etc/php5/apache2/php.ini
C /tmp
A /tmp/do
root@localhost:~#
Step 2: 疑わしきファイルをローカルファイルシステムにコピー
docker diff
コマンドの結果から、疑わしきファイルをローカルへダウンロードし、調査を行います。
ここでは、C /etc/shadow
の結果に注目し、調査を行います。
Command: docker cp
root@localhost:~# docker cp wordpress:/etc/shadow .
変更箇所を明らかにするために、新しいコンテナを実行し、そこからファイルを抽出。オリジナルと比較することで確認することもできます。
root@localhost:~# docker run -d lamp-wordpress
8c6feb6a45be96a6252b3c4f8d336ea8be0b2a552621ec20dfde8fdab83b8444
root@localhost:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c6feb6a45be lamp-wordpress "./run.sh" 21 seconds ago Up 11 seconds 80/tcp boring_wilson
e5813268132b lamp-wordpress "./run.sh" 14 minutes ago Up 13 minutes 80/tcp wordpress
root@localhost:~# docker cp 8c6feb6a45be:/etc/shadow original_shadow
root@localhost:~# diff original_shadow shadow
21a22
> service:$./9/Kdyr/9BJ{BLOCKED}xV0:18231::::::
root@localhost:~#
Step 3: コンテナ内でシェルを起動し探索
コンテナへアクセスし、調査を行うことも可能です。
Command: docker exec
オプション
名前/省略形 | 説明 |
---|---|
--interactive , -i | アタッチされていなくても STDIN は開放し続けます。 |
--tty , -t | 擬似 TTY を割り当てます。 |
root@localhost:~# docker exec -it wordpress bash
root@e5813268132b:/#
参考情報
- Docker ドキュメント日本語化プロジェクト, http://docs.docker.jp/
- HackTricks, Docker Forensics, https://book.hacktricks.xyz/forensics/basic-forensic-methodology/docker-forensics
Pentester Academy - Free Labs
Pentester Academyが提供する「Attack Defense」では、「コンテナセキュリティ(CONTAINER SECURITY)」に関する次のラボが無料で提供されています。
- Docker Registry - Insecure Docker Registry II
- Docker Registry - Corrupting Source Image
- Docker Forensics - Flag File Forensic Recovery I
- Docker Forensics - System Backdoor