1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dockerイメージレイヤから「削除したはずの認証情報ファイル」を復元できた話

Posted at

例えば、Docker コンテナ内で認証情報を必要とするコマンド(例:AWS CLI など)を実行したい場合に、コンテナ内に認証情報ファイルをコピーして、コマンドを実行したらすぐに削除したとします。

Dockerfile
FROM alpine:3.21.3

# 認証情報ファイルをコピー
COPY credentials /tmp/credentials

# コマンド実行後に認証情報ファイルを削除
RUN 認証情報が必要なコマンド && rm -f /tmp/credentials

コンテナを起動してコンテナ内に入ると/tmp/credentialsは存在していません。
RUNでファイルを削除しているためです。

一見するとセキュリティ面では問題なさそうに思えますが、RUNのイメージレイヤで認証情報ファイルは削除されたものの、COPYのレイヤにはファイルが残ったままになっているため危険であると言われています。

この事は知識としては知っていたのですが、ふと、このファイルを復元(取り出し)できるのか?が気になり、検証を行ってみました。

先に結論から書きますと、ファイルの復元ができました

検証環境

  • Ubuntu 22.04.5 LTS (ホスト機)
  • Docker version 28.0.1

認証情報ファイルが存在しないことを確認する

まずは、作業用のディレクトリを作成します。

mkdir ~/work
cd ~/work

Dockerfile を作成します。中身は先ほど登場したものと同じです。
認証情報が必要なコマンドの箇所は(AWS CLI のコマンドでも良かったのですが)簡単に使えるtouch /tmp/test.txtで代替します。

Dockerfile
FROM alpine:3.21.3

# 認証情報ファイルをコピー
COPY credentials /tmp/credentials

# コマンド実行後に認証情報ファイルを削除
RUN touch /tmp/test.txt && rm -f /tmp/credentials

credentialsファイルを作成します。検証用なので中身は適当です。

$ echo "abcd1234" > credentials

ディレクトリ構造を確認します。

work
├── credentials
└── Dockerfile

Docker コンテナイメージをビルドします。

$ docker build -t test-credentials:v1 .

コンテナを起動します。

$ docker run -it --rm test-credentials:v1 /bin/sh

コンテナ内でlsコマンドを実行します。
/tmp/credentialsが存在しないことを確認できました。

$ docker run -it --rm test-credentials:v1 /bin/sh
/ # ls /tmp
test.txt
/ # 

認証情報ファイルを復元する

では、本題の復元作業に入ります。

まずは、コンテナイメージの履歴を確認します。
上から2つ目が認証情報ファイルをコピーした履歴のようです。

$ docker history test-credentials:v1 
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
baaa7f5efecb   3 hours ago    RUN /bin/sh -c touch /tmp/test.txt && rm -f …   0B        buildkit.dockerfile.v0
<missing>      3 hours ago    COPY credentials /tmp/credentials # buildkit    10B       buildkit.dockerfile.v0
<missing>      2 months ago   CMD ["/bin/sh"]                                 0B        buildkit.dockerfile.v0
<missing>      2 months ago   ADD alpine-minirootfs-3.21.3-x86_64.tar.gz /…   7.83MB    buildkit.dockerfile.v0

次に、コンテナイメージを tar ファイルに保存します。

$ docker image save -o image.tar test-credentials:v1

tar ファイルを展開します。

mkdir my_image
tar -xf image.tar -C my_image
$ tree ./my_image
./my_image
├── blobs
│   └── sha256
│       ├── 08000c18d16dadf9553d747a58cf44023423a9ab010aab96cf263d2216b8b350
│       ├── 43f60cf296e3de5b33a7e40bd413fb1b6bef27cdfd6511a9c62ec1d67dfa9282
│       ├── 45323140c02695850874d0d9d6b5604630e1db83771f2fe6217a510b36831e87
│       ├── 546e58a06b0be2997519913950b91459021da27c98a02aed826ab6fd0fb45e33
│       ├── a7b3e0a86c7b50efa82ae1162d4ef1c10164eaf17c3bc2886790a10ab1fb0b2f
│       ├── baaa7f5efecb76eb5857eed6791c35191cdcdea97081bf9a43c4fcc61ad0a7dd
│       ├── cf9c58598bc7725d655275a489b8c78fa54e9b386ce05806dd3d92dee05764bf
│       └── d60bba0bcb4bd87500469f4d9a40c42401516589cb0c3fdb311ea5feb1062b4e
├── index.json
├── manifest.json
├── oci-layout
└── repositories

manifest.json ファイルを確認します。
Layersにはレイヤの実行順序が定義されているようなので、上から2つ目の546e58a0...がコピーのレイヤだと当たりを付けます。

manifest.json
[
  {
    "Config": "blobs/sha256/baaa7f5efecb76eb5857eed6791c35191cdcdea97081bf9a43c4fcc61ad0a7dd",
    "RepoTags": [
      "test-credentials:v1"
    ],
    "Layers": [
      "blobs/sha256/08000c18d16dadf9553d747a58cf44023423a9ab010aab96cf263d2216b8b350",
      "blobs/sha256/546e58a06b0be2997519913950b91459021da27c98a02aed826ab6fd0fb45e33",
      "blobs/sha256/a7b3e0a86c7b50efa82ae1162d4ef1c10164eaf17c3bc2886790a10ab1fb0b2f"
    ],
    "LayerSources": {
      "sha256:08000c18d16dadf9553d747a58cf44023423a9ab010aab96cf263d2216b8b350": {
        "mediaType": "application/vnd.oci.image.layer.v1.tar",
        "size": 8120832,
        "digest": "sha256:08000c18d16dadf9553d747a58cf44023423a9ab010aab96cf263d2216b8b350"
      },
      "sha256:546e58a06b0be2997519913950b91459021da27c98a02aed826ab6fd0fb45e33": {
        "mediaType": "application/vnd.oci.image.layer.v1.tar",
        "size": 2560,
        "digest": "sha256:546e58a06b0be2997519913950b91459021da27c98a02aed826ab6fd0fb45e33"
      },
      "sha256:a7b3e0a86c7b50efa82ae1162d4ef1c10164eaf17c3bc2886790a10ab1fb0b2f": {
        "mediaType": "application/vnd.oci.image.layer.v1.tar",
        "size": 3072,
        "digest": "sha256:a7b3e0a86c7b50efa82ae1162d4ef1c10164eaf17c3bc2886790a10ab1fb0b2f"
      }
    }
  }
]

blobs/sha256/546e58a0...の正体は tar ファイルなので、これを展開します。
LayerSourcesmediaTypetarと書かれてある。

cd my_image
mkdir layer
tar -xf blobs/sha256/546e58a06b0be2997519913950b91459021da27c98a02aed826ab6fd0fb45e33 -C layer

展開先ディレクトリの中身を確認します。
ファイルを復元できました。

$ tree ./layer
./layer
└── tmp
    └── credentials # 認証情報ファイル

2 directories, 1 file

$ cat ./layer/tmp/credentials 
abcd1234

さいごに

筆者は使ったことがありませんが、dive という Docker イメージレイヤを視覚的に調査できるツールがあるようで、これを使えばもっと簡単にできたりするのかも知れません。

参考記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?