[alpine] CVE-2019-13638への対応 

```
#!/bin/sh -eo pipefail
trivy --exit-code 1 --quiet --severity HIGH,CRITICAL --auto-refresh --ignore-unfixed -c --auto-refresh company-nginx
2019-08-14T05:34:12.729Z	INFO	Removing image caches...
2019-08-14T05:34:12.730Z	INFO	Updating vulnerability database...
2019-08-14T05:36:00.080Z	INFO	Updating nvd data...
2019-08-14T05:36:33.431Z	INFO	Updating alpine data...
2019-08-14T05:36:35.409Z	INFO	Updating redhat data...
2019-08-14T05:36:38.522Z	INFO	Updating debian data...
2019-08-14T05:36:42.107Z	INFO	Updating debian-oval data...
2019-08-14T05:36:46.868Z	INFO	Updating ubuntu data...
2019-08-14T05:36:53.949Z	INFO	Detecting Alpine vulnerabilities...

company-nginx (alpine 3.9.4)
============================
Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| patch   | CVE-2019-13638   | CRITICAL | 2.7.6-r4          | 2.7.6-r6      | patch: OS shell command        |
|         |                  |          |                   |               | injection when processing      |
|         |                  |          |                   |               | crafted patch files            |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
Exited with code 1
```

trivy実行時にalpineに脆弱性があるよと怒られました。
インフラ全然わからないマンの僕が色々調べながら対応したので、将来自分で見直すために、ログとして対応内容と調査した内容をまとめます。

# 前提
今回エラーが発生したのはnginx用のDockerfileでした。
以下、Dockerfileの抜粋です。

```dockerfile
FROM nginx:1.17.1-alpine

RUN set -e && \
  apk update && \
  apk upgrade && \
  apk add --update --no-cache \
  bzip2
...
```

# 調査1: 報告があった脆弱性の概要
今回報告があった脆弱性について、冒頭に挙げたtrivyの出力内容から VULNERABILITY ID（`CVE-2019-13638`） を抽出し、ググってみました。
出てきたのは以下の報告書でした。
https://nvd.nist.gov/vuln/detail/CVE-2019-13638

> GNU patch through 2.7.6 is vulnerable to OS shell command injection that can be exploited by opening a crafted patch file that contains an ed style diff payload with shell metacharacters. The ed editor does not need to be present on the vulnerable system. This is different from CVE-2018-1000156.

なんとなく、「シェルコマンドインジェクションをされる可能性があるよ」的なことを言っているのがわかります。ただ、具体的な対応方法については読み取れませんでした。
先ほどの引用から、「2.7.6までのGNU patchは脆弱性があるよ」ということも読み取れます。これについては、trivyの出力内容からも、**「多分 GNU patch 2.7.6-r6を入れればいいんだろうな」**ということはわかります。

ここで、GNU patchってなんぞや、という疑問が浮かびました。

# 調査2: GNU patch
GNUとは、linuxなどのライセンスを管理している団体の名称です。
GNUが配布しているpatchパッケージのことをGNU patchと表記しているようでした。
patchというと、既存のライブラリに対する修正用の差分適用ファイルのことかなと思っていたのですが、ここでは`patch`コマンドで呼び出すライブラリそのものを指します。

# 仮説
調査1と調査2を踏まえて、「現在Dockerのベースイメージとして利用しているバージョンのalpineに、脆弱性に対応したpatchライブラリが含まれていないのではないか」という仮説が生まれます。
これをもとに、まずはalpineイメージのバージョンアップデートを試みました。

# 試行1: ベースイメージのバージョンアップ
Dockerhubのnginxのページから、現状のベースイメージの最新版を探します。
nginxのページ: https://hub.docker.com/_/nginx
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144745/31f96b1a-7f2f-5173-afc9-883c49ee3698.png)

それっぽいものがあったので、一旦雑にDockerfileの記述を修正してみます。

```dockerfile
FROM nginx:1.17.2-alpine

RUN set -e && \
  apk update && \
  apk upgrade && \
  apk add --update --no-cache \
  bzip2
...
```
修正を保存し、trivyコマンドを叩いてみます。

```
#!/bin/sh -eo pipefail
trivy --exit-code 1 --quiet --severity HIGH,CRITICAL --auto-refresh --ignore-unfixed -c --auto-refresh company-nginx
2019-08-14T04:36:37.190Z	INFO	Removing image caches...
2019-08-14T04:36:37.194Z	INFO	Updating vulnerability database...
2019-08-14T04:41:41.458Z	INFO	Updating debian-oval data...
2019-08-14T04:41:45.945Z	INFO	Updating ubuntu data...
2019-08-14T04:41:49.828Z	INFO	Updating nvd data...
2019-08-14T04:42:19.808Z	INFO	Updating alpine data...
2019-08-14T04:42:22.014Z	INFO	Updating redhat data...
2019-08-14T04:42:25.174Z	INFO	Updating debian data...
2019-08-14T04:42:31.060Z	INFO	Detecting Alpine vulnerabilities...

company-nginx (alpine 3.10.1)
=============================
Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 1)

+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| patch   | CVE-2019-13638   | CRITICAL | 2.7.6-r5          | 2.7.6-r6      | patch: OS shell command        |
|         |                  |          |                   |               | injection when processing      |
|         |                  |          |                   |               | crafted patch files            |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
Exited with code 1
```

ダメっぽい。alpineのバージョンは上がりましたが、まだ脆弱性対応済みのpatchパッケージが含まれていないようです。
ベースイメージのアップデートで対応できないので、個別にバージョンを指定してpatchパッケージをインストールしてみようと思います。

# 調査3: apk
alpineでは、パッケージマネージャとしてapkを使用します。
apkのコマンドについて詳しくないので、コマンドを叩きながら調査してみようと思います。

```
$ docker pull alpine
jUsing default tag: latest
latest: Pulling from library/alpine
050382585609: Pull complete
Digest: sha256:6a92cd1fcdc8d8cdec60f33dda4db2cb1fcdcacf3410a8e05b3741f44a9b5998
Status: Downloaded newer image for alpine:latest
```

alpineのイメージをpullできたので、コンテナを立てて中に入ります。

```
$ docker run -it alpine sh
/ #
```

apkのコマンド一覧を表示します。

```
/ # apk --help
apk-tools 2.10.4, compiled for x86_64.

Installing and removing packages:
  add       Add PACKAGEs to 'world' and install (or upgrade) them, while ensuring that all dependencies are met
  del       Remove PACKAGEs from 'world' and uninstall them

System maintenance:
  fix       Repair package or upgrade it without modifying main dependencies
  update    Update repository indexes from all remote repositories
  upgrade   Upgrade currently installed packages to match repositories
  cache     Download missing PACKAGEs to cache and/or delete unneeded files from cache

Querying information about packages:
  info      Give detailed information about PACKAGEs or repositories
  list      List packages by PATTERN and other criteria
  dot       Generate graphviz graphs
  policy    Show repository policy for packages

Repository maintenance:
  index     Create repository index file from FILEs
  fetch     Download PACKAGEs from global repositories to a local directory
  verify    Verify package integrity and signature
  manifest  Show checksums of package contents

Use apk <command> --help for command-specific help.
Use apk --help --verbose for a full command listing.

This apk has coffee making abilities.
```

ここではaddコマンドが適切そうということがわかりました。
そういえば元のDockerfileで `apk add ...`というコマンドを叩いていました。

```dockerfile
RUN set -e && \
  apk update && \
  apk upgrade && \
  apk add --update --no-cache \
  bzip2
```

`apk add`コマンドの引数に,バージョンを指定したpatchパッケージを追記してみます。

# 試行2: apk add [package name]=[version]

```dockerfile
FROM nginx:1.17.2-alpine

RUN set -e && \
  apk update && \
  apk upgrade && \
  apk add --update --no-cache \
  bzip2 \
  patch=2.7.6-r6

...
```

上記の修正を保存して、再度trivyコマンドを叩きます。

```
#!/bin/sh -eo pipefail
trivy --exit-code 1 --quiet --severity HIGH,CRITICAL --auto-refresh --ignore-unfixed -c --auto-refresh $DOCKER_IMAGE_REPO:$CIRCLE_SHA1
2019-08-14T05:40:29.881Z	INFO	Removing image caches...
2019-08-14T05:40:29.882Z	INFO	Updating vulnerability database...
2019-08-14T05:42:48.515Z	INFO	Updating nvd data...
2019-08-14T05:43:23.457Z	INFO	Updating alpine data...
2019-08-14T05:43:27.102Z	INFO	Updating redhat data...
2019-08-14T05:43:30.237Z	INFO	Updating debian data...
2019-08-14T05:43:33.431Z	INFO	Updating debian-oval data...
2019-08-14T05:43:38.458Z	INFO	Updating ubuntu data...
2019-08-14T05:44:05.219Z	INFO	Detecting Alpine vulnerabilities...
2019-08-14T05:44:05.222Z	INFO	Updating yarn Security DB...
2019-08-14T05:44:07.099Z	INFO	Detecting yarn vulnerabilities...

****************/*************/company:****7188208f40d4faf65 (alpine 3.9.4)
=========================================================================================================================
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)


app/yarn.lock
=============
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
```

通りました。


# おわりに

雑なログで恐縮です。かつ、もろもろの解釈がややあやふやな気がしているので、「この表現は適切ではないよ」などあれば、コメントいただけると嬉しいですm(_ _)m