去年は問題なかったイメージ
イメージの監査とは、コンテナの元になるイメージが何を動かし、どのバージョンを持ち、古いものがないかを確かめることです。古い部品が残っていると、すでに知られた欠陥を、そのまま使われてしまいます。
あるチームが1年前に Web サーバーのイメージを作り、それ以来ずっと動かしてきました。動いていたので、誰も触りませんでした。その1年のうちに、中のプログラムで3つの欠陥が見つかりましたが、チームは一度も見ず、見つけたのはスキャナーでした。
今日は、守る側の目で、攻撃される前にイメージを調べます。
このレッスンのゴール
メモ
イメージが何を動かし、どのバージョンを持ち、古いものがないかを調べられる。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| イメージ | プログラムと、その動作に必要なものを包んだ複製。コンテナはここから起動する | |
| タグ | イメージ名のコロンのあとにある札 | 1.27.5-alpine |
| 固定 | 正確なバージョンを1つ指定して、知らないうちに変わらないようにすること | |
| パッケージ | イメージの中に入れた、1つのプログラムやライブラリ | |
| 勧告 | 既知の欠陥を、どのバージョンで直したかを伝える知らせ | |
| スキャン | 入っているものを、既知の欠陥の一覧と比べること |
学生が入力するセルは、このプレビューでは空白です。
タグは、動かしているバージョンを示す
コンテナはイメージから起動します。イメージの名前の終わりには、nginx:1.27.5-alpine のようなタグが付きます。
latest というタグは、今日いちばん新しいものを意味します。足元で変わってしまいます。固定したタグは、正確なバージョンを1つ示すので、何を動かしているかがわかり、いつ替えるかを自分で決められます。
web サービスは、どのイメージを動かしているか
docker inspect web --format '{{.Config.Image}}'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
中の nginx はどのバージョンか
docker exec web nginx -vここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
2つの Run が書いたもの
1つ目は nginx:1.27.5-alpine を書きました。タグがバージョンなので、このイメージは固定されています。2つ目は nginx version: nginx/1.27.5 を書きました。
この2つの答えは一致するはずです。タグとプログラムが違うことを言うなら、誰かがイメージを変えています。
各プロセスは誰が動かしているか
docker exec web ps -o user,args | head -n 3ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
root とワーカー
Run は、見出しを書き、次にマスタープロセスを動かす root の行、そのあとワーカーを動かす nginx の行を書きました。
マスターは、ポート80を開くために root です。訪問者に応えるワーカーは、普通のアカウント nginx で動きます。ワーカーの欠陥で攻撃者が得るものは、ずっと小さくなります。全部が root なら、同じ欠陥でコンテナのすべてが手に入ります。
スキャンの前に、一覧を作る
スキャナーは3つのことをします。パッケージを並べ、欠陥とその直し方の一覧を読み、2つを比べます。
1つ目と3つ目は、ラボでできます。本物のスキャナーは欠陥の一覧をインターネットから取りますが、ラボには出口がありません。だから、作り話の勧告を2つ打ちます。
パッケージはいくつ入っているか
docker exec web apk info 2>/dev/null | wc -lここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
2つのバージョンを見る
docker exec web apk info -v 2>/dev/null | grep -E '^(zlib|musl)-[0-9]'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
一覧
試したときは、数は68で、2行は musl-1.2.5-r9 と zlib-1.3.1-r2 でした。各行は、名前、バージョン、ビルド番号です。
作り話の勧告を1つ。「zlib は 1.3.2-r0 で直った」。Alpine は、2つのバージョンの比較を、オフラインでしてくれます。
入っている zlib は、直った版より古いか
docker exec web apk version -t 1.3.1-r2 1.3.2-r0ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
musl を、同じ版の勧告と比べる
docker exec web apk version -t 1.2.5-r9 1.2.5-r9ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
記号の意味
1つ目の Run は < を書きました。入っている版は、直った版より古いので、このパッケージは更新が要ります。2つ目は = を書きました。すでに直った版です。
記号 > なら、直った版より新しいということです。スキャンのすべては、一覧、勧告、比較の3つです。
例: スキャンが決めること
| パッケージ | 入っている版 | 直った版 | 結果 |
|---|---|---|---|
| zlib | 1.3.1-r2 | 1.3.2-r0 | 古い。更新する |
| musl | 1.2.5-r9 | 1.2.5-r9 | 同じ。直っている |
| curl | 8.12.1-r1 | 8.12.0-r0 | 新しい。直っている |
学生が入力するセルは、このプレビューでは空白です。
イメージは環境変数に何を持っているか
docker inspect web --format '{{json .Config.Env}}'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
一度スキャンして何も出ないと、二度とスキャンしない人が多くいます。新しい欠陥は毎週見つかるので、先月きれいだったイメージが、今日もきれいとは限りません。予定を決めてスキャンし、イメージが変わるたびにもう一度行いましょう。
ラボには見せられないこと
ラボは、イメージの取得、ビルド、スキャンができません。だから、イメージのファイルではなく、動いているサービスを調べました。試験機では、環境変数の Run が書いたのは、バージョンのように、イメージ自身が決めた値だけでした。それが、あるべき姿です。
その一覧にパスワードがあれば、漏えいです。コンテナを調べられる人なら、誰でも読めてしまいます。
発展: 直したあとで
ラボの修正を終えたら、docker exec web lab-check を実行します。このレッスンの3つの Run をもう一度実行し、1文を書きましょう。どれか変わったでしょうか。
堅くしたのは設定です。イメージとパッケージは、そのままです。設定を直しても、パッケージは更新されません。