KiSAKU
技術系約5分で読めます

Criticalが4件並んだ日にやったこと

公開

朝、通知を見たらCriticalが4件並んでいました。どれも同じ相手、Next.js本体です。

この日にやったことを順に書きます。結論から言うと、上げました。ただ、上げる前にやったことのほうが本題です。

この記事で扱うこと

脆弱性の通知が来たときに、何をどの順で確かめたか。自分のサイトが実際に影響を受けるのかを切り分ける手順と、それでも上げた理由です。

まず、中身を読む

4件は、実は2種類でした。同じものが2つのファイルで検出されているので、件数が倍に見えていました。使っているものを書いた一覧と、実際に入った版を固定した一覧の2つです。

種類 内容
A Windowsで動かしているサーバーでの、認証不要の遠隔コード実行
B 画像最適化の機能で、AVIF形式を扱ったときの遠隔コード実行

どちらも「認証不要」で「遠隔からコードを実行される」。言葉としては、これ以上ないくらい重い部類です。

Aは、条件に当てはまらなかった

Aの説明には、条件がはっきり書いてありました。WindowsのファイルシステムでNext.jsのサーバーが動いている場合に成立する、と。

そして、LinuxとmacOSは影響を受けないと明記されていました。

このサイトの本番はVercelで動いています。Linuxです。開発しているのもMacです。どちらも対象外でした。

「Critical」は自分への影響度ではない

重大度は、その脆弱性が最悪の場合にどれだけひどいかを表しています。自分の環境で成立するかどうかは、また別です。

色と数字だけ見て慌てると、条件を読まずに動くことになります。読めば1分でした。

Bは、入口の広さを自分で確かめた

Bのほうは、条件が「AVIF形式の画像を最適化したとき」です。攻撃者が用意した画像を最適化させられると成立します。

このサイトは画像の最適化機能を使っています。ここで確かめるのは、「誰でも好きな画像を最適化させられる状態か」です。

設定を見ると、最適化を許可している場所が2つだけ指定してありました。

remotePatterns: [
  { hostname: "localhost", port: "8080", ... },
  { hostname: "cms.kisaku.site",
    pathname: "/wp/wp-content/uploads/**" },
]

つまり、CMSの画像置き場にあるファイルしか最適化できません。任意のURLを渡しても弾かれます。

そこに置くには、CMSにログインして画像をアップロードする必要があります。入口はかなり狭いと言えます。

「狭い」は「無い」ではない

ここで止めたくなりますが、狭いだけで塞がってはいません。

CMSのログインが破られれば成立します。そしてCMSは共用サーバー上のWordPressで、攻撃対象としてはありふれた構成です。「入口が狭いから大丈夫」は、入口が破られない前提に乗っています。

結局、上げた

Aは対象外、Bは入口が狭い。それでも上げました。

理由は単純で、上げない理由のほうが薄かったからです。

上げる 上げない
作業量 修正版への更新1回 0
壊れる可能性 細かい版の更新なので低い —
放置した場合 — 入口が破られた時点で成立する

大きな作り替えを伴う更新なら、慎重になる理由があります。今回は末尾の数字が1つ上がるだけの修正版で、その中身も「問題のある機能を止める」というものでした。

本番に入るものと、そうでないものを分けて数える

更新したあと、残りを確かめました。ここで1つ、見方を変えています。

そのまま数えると12件残っていました。ところが「本番に配るものだけ」で数え直すと0件です。

npm audit --omit=dev
found 0 vulnerabilities

残っていた12件は、全部開発中にしか動かない道具のものでした。型を生成するツールが使っている、さらにその中のライブラリです。

配られないものは、訪問者に届かない

これらはビルドのときに自分のマシンで動くだけで、配信されるファイルには入りません。訪問者のブラウザにも、サーバーにも届きません。

0件にはしたいのですが、直すには型生成ツールを大きく更新する必要があり、そちらのほうが壊れる可能性が高い。今回は見送って、理由を書き残しました。

数字を0にすることが目的になると、危険度の低いもののために動いているものを壊します。分けて数えると、どちらを急ぐかが決まります。

やったことをまとめると

順番 やったこと かかった時間
1 4件が実は2種類だと確認 1分
2 条件を読んで、対象外を1つ外した 2分
3 残りの入口の広さを設定で確かめた 5分
4 更新して、型検査を通した 5分
5 本番に入るものだけで数え直した 1分

手を動かしたのは4だけで、残りは読んで確かめる時間でした。

今回の学び

まず、重大度は「最悪の場合」の話であって、自分への影響ではないということ。条件が書いてあるので、読めば当てはまるかどうかが分かります。今回は片方が最初から対象外でした。

次に、「入口が狭い」で止めないこと。狭いのは事実でしたが、狭さはこちらの設定に依存しています。設定を変えた日に広がるかもしれません。狭いことを理由に放置すると、その理由を覚えている人がいなくなった時点で危なくなります。

そして、数える範囲を先に決めること。全部で12件と、配信されるものの中で0件では、判断がまったく変わります。件数を減らすこと自体を目的にすると、動いているものを壊しにいくことになります。

この記事を共有する

Xでポストはてブ
← ブログ一覧へ戻る