Koa.js の脆弱性分析の更新
少し前ですが、2018 年にKoa.jsに影響を与えた脆弱性について書きました。最新バージョンの Koa を使用していたのに、2022 年の時点で 2018 年からの問題に対処しなければならなかったことに不満を感じていました。4年が経過しました。それは長い時間。きっと問題はもうありません!? そして、それは同時にあり、同時にありませんでした。つまり、私は間違っていたと同時に正しかったということです。そのため、以前の投稿を更新して、その方法を説明します。
- 特定のケースで、Sonatype と Dependency Track がバージョン情報で動作していないと不当に非難しました
- 私は脆弱性について同時に正しいことも間違っていることもあります
OSS インデックスにはバージョン情報があります
以前の投稿を読んだことがある方は、この問題が私に影響を与えていないと結論付けたことを覚えているでしょう。良いニュースは、私が正しかったということです。悪いニュースは、Sonatype が OSS Index for Dependency Track によって提供されたデータにバージョン番号が含まれていないことを不当に非難したことです。彼らは情報を持っていることがわかりました。見えるはずだと思っていたところに見えなかっただけです。2022 年 11 月 22 日に撮影された以下のスクリーンショットを参照してください。

依存関係トラック (DT) が上記のページに表示されているとおりに機能しない可能性は非常に高いですが、DT が OSS インデックスから取得したデータがどのように見えるかを確認することは気にしませんでした。DT は OSS Index へのリンクを表示しました。ここで詳細を確認できます。クリックしてこのページにたどり着きました。
今日、Sonatype によって、バージョン番号が利用可能であることがわかりました。私は他の場所を見なければなりません。実際、アカウントにログインして Koa を検索するか、上のスクリーンショットの [Koa の詳細を表示] ボタンをクリックすると、見つけることができます。以下のスクリーンショットを参照してください。

だから私は間違っていました。Sonatype はデータベースに情報を持っています。問題はプレゼンテーション層にあります。脆弱性が実際に議論されているページに影響を受けるバージョンがリストされていて、必要に応じて確認して検証できるようにすることをお勧めします.
私は Sonatype OSS Index がバージョン情報を持っていないと不当に非難しました。また、バージョン情報が利用できない場合、依存関係の名前に基づいて純粋に報告することをいとわない Dependency Track を不当に非難しました。(後者が真か偽かを調べる必要がありますが、私は確認していません。)
まだあきらめないでください!議論すべきよりエキサイティングなことは、実際の脆弱性と、OSS Index の脆弱性レポートに対する (できれば) 今後の変更です。脆弱性から始めましょう。
クロスサイト スクリプティング
Sonatype は、以下の思考プロセスに基づいて XSS を Koa に帰しました。
Koa は、Koa を使用する開発者ではなく、HTML 応答に URL を書き込むエンティティです。
開発者が提供された URL を許可リストに照らして検証し、オープン リダイレクトを防止することを期待するのは間違いなく合理的です。しかし、開発者としては、redirect() メソッドに渡す URL の XSS サニタイズについて心配する必要はないと思います。
Koa は、このコンテキストで XSS を気にかけているようです。これは、それを防ぐコードが既にあり、HTML に書き込むときに URL をエンコードする HTML エンティティです。
私はある程度同意します。たとえば、次のような場合は同意しません。
redirect() メソッドに渡す URL の XSS サニタイズについて心配する必要はないと思います。
あなた (開発者) が提供したリダイレクト メソッドに有効で安全な URL を渡す場合、(明らかに) XSS について心配する必要はありません。ユーザーが提供したデータの全部または一部を渡す場合、それは、開発者であろうとセキュリティ専門家であろうと、常に気にしなければならないことです。それでも、Koa が開発者を助けてくれると期待するのは大げさではありません。
私がどこから来たのかを理解するのに役立つことを願って、良い例を挙げましょう。以下の例では、ユーザーが提供したデータを応答本文でブラウザーに返します。これは、検証、サニタイズ、またはエンコードなしで行います。
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = ctx.query.payload;
});
app.listen(4444);
* Trying 127.0.0.1:4444...
* Connected to 127.0.0.1 (127.0.0.1) port 4444 (#0)
> GET /?payload=<img%20src=x%20onerror=alert(1)> HTTP/1.1
> Host: 127.0.0.1:4444
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 28
< Date: Wed, 23 Nov 2022 10:59:17 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host 127.0.0.1 left intact
<img src=x onerror=alert(1)>%
- 応答本文でブラウザに何をどのように渡すかを考えてください
- 応答の Content-Type ヘッダーの値を検討してください (そして、おそらく明示的に制御するのが最善です!)
- デフォルトでは、Koa は に渡された値に基づいて Content-Type ヘッダーの値を自動的に調整することに注意して
ctx.body
ください。(たとえばaaa
、 を渡してみて、どのように変化するかを確認してください)
ctx.body
上記の「XSS」の例を考えると、ctx.redirect()
. Sonatype を再度引用します。
Koa は既にコードを持っているため、このコンテキストでは XSS を気にかけているようです。
これは、Koa がこのコンテキストで XSS を気にかけなかった場合、同様に、 についても気にかけなかった (そして気にかけるべきではなかった) 場合ctx.body
、誰も XSS 脆弱性としてフラグを立てなかっただろうということですか? それはかなり面白いです。こことここに文書化されている手ごわいに関する私の以前の分析といくつかの類似点があることに気付きました。
これまで私が言ったことは何でも言いますが、XSS はたまたまそこにあります…そして同時にではありません。そんなことがあるものか?単純!そこにありますが、次の場合を除き、悪用することはできません。
- 被害者は古い Web ブラウザを使用しており、かつ
- Koa の
ctx.redirect()
, ANDを使用して開発者によって実装されたオープン リダイレクトがあります。 - 開発者は、ユーザーが提供するすべてのデータを完全に信頼し、それを逐語的に
ctx.redirect()
Sonatype のレポート ページには、今日のスクリーンショットからわかるように、「クロスサイト スクリプティングにつながるオープン リダイレクト」と書かれていました。私の以前の投稿では、「オープン リダイレクト」の部分について質問しました。
まず、オープンリダイレクトがありませんでした。開いた場合にのみ開いており、2 つの PoC (オリジナルと私のもの) の違いがこれを明確に示しています。
Sonatype は、Koa がオープン リダイレクトを防止する責任を負わないことにも同意します。彼らの懸念、私の懸念、そして他の全員の主な懸念は XSS でした。オープン リダイレクトを使用することは、混乱を招くだけでした。同時に、後で説明するように、技術的には不合理ではありませんでした。(脆弱性スコアリングにも影響します。)
前述のように、Koa の動作を悪用するには、オープン リダイレクトが必要です。だが:
- Koa は、オープン リダイレクトを防止する責任を負いません (前述のとおり)
- Koa は
ctx.redirect()
開発者の発言なしでは実行されません - Koa は開発者にリダイレクトの使用を強制しません
したがって、もう 1 つの保護レイヤーがあります。それは、ユース ケースです。開発者は、ブラウザーがリダイレクトされる場所を制御したくない可能性はどのくらいありますか? 非常にありそうもない。これは、ほとんどの場合、開発者がユーザー制御のデータをctx.redirect()
別の文字列に追加して渡すことを意味します。そのため、以下に示す例のようなことが起こる可能性が最も高くなります。
ctx.redirect(`http://website.example.org/search?q=${userInput}`);
ctx.redirect(`/search?topic=${userInput}`);
脆弱性スコアリング
前のセクションの最後で説明したように、バグが悪用されるには 3 つの条件を満たす必要があります。
- どのバージョンのブラウザを使用するかは、エンド ユーザー次第です。
- リダイレクトメソッドの使用とその使用方法は開発者次第です
安全でない方法でのリダイレクト方法の使用が攻撃ベクトルであることも強調する必要があります。エクスプロイトを成功させるには、攻撃ベクトルが必要です。Koa は攻撃ベクトルを提供しません。開発者が行います。
これを、NIST が提供する「ソフトウェアの脆弱性」の定義と関連付けてみましょう。

私が強調したい部分は、「悪用される可能性がある」ということです。Koa をソフトウェア ライブラリとして使用します。最初に必要な攻撃ベクトルを作成せずに悪用できますか? いいえ。つまり、ソフトウェア ライブラリである Koa の観点からは、攻撃ベクトルは提示されません。それがなければ、搾取は不可能です。定義を厳密に解釈すると (私はそうしています)、Koa の動作を脆弱性とは言えません。
攻撃ベクトルなしで CVSS スコアを計算してみましょう。

攻撃ベクトルがなければスコアはありません。これは、NIST が提供するソフトウェア脆弱性の定義と一致していると言えます。
実験して、攻撃ベクトルが存在する架空のシナリオを作成してみましょう。

架空の攻撃ベクトル以外にも、まだいくつかの問題があります。エクスプロイトを成功させるには古いブラウザが必要なため、攻撃の複雑度は高に設定されています。攻撃者は、被害者に古いブラウザをダウンロードしてインストールするよう説得する必要があります。
その意味で、ユーザー インタラクションのベース メトリックは実際にはそれに関するものではありませんが、ユーザー インタラクションは必要です。このシナリオでは、XSS を悪用するためにユーザーの操作が必要かどうかは、Koa ではなく、Web アプリケーションがリダイレクトをどのように使用したかによって決まります。また、注入された JavaScript は、HTML 応答内のリンクをクリックするというユーザーの操作が最初に必要だったため、単独では実行されないことにも注意してください。
では、これに脆弱性スコアを強制するにはどうすればよいでしょうか? 何かを選ばなければなりません。希望的観測、最悪の事態を想定して、好きなように。1 つ確かなことは、そもそも行うべきではない計算を行っており、結果が現実からかけ離れているため、言葉が見つからないということです。
次に重要なのは、影響指標です。影響を与えるには、Web アプリケーションが何をしようとしているのかを知る必要があります。しかし、Web アプリケーションの脆弱性スコアは計算していません… コンテキストを考えると、この XSS は Koa にまったく影響を与えません。Koa は、独自に機密情報を処理または処理しません。このバグは、可用性や整合性には影響しません。これにより、攻撃ベクトルを計算に強制した後でも、最終的なスコアは 0.0 になります。

問題は、事実を報告するかフィクションを報告するかということです。
Sonatype は、2019 年に CVSSv3.1 でリリースされたScoring Vulnerabilities in Software Librariesの公式ガイダンスに注目しました。私はそれについて知らなかったことを認めますが、それは良いことでも悪いことでもあります。暴言の投稿になっていたので良かったです。悪いのは、もっと早く見ていたら、それが正しい方法ではないと説明しようとする前に、すべての希望を失っていたからです。それで、公式のガイダンスは何と言っていますか?
ライブラリ内の脆弱性の影響をスコアリングする場合... アナリストは、合理的な最悪の実装シナリオをスコアリングする必要があります。可能であれば、CVSS 情報でこれらの仮定を詳述する必要があります。
答えは、脆弱性スコアリングはフィクションに基づいているということです。
また、「合理的な最悪の実装シナリオ」とは何ですか? Koa を使用した多くのプロジェクトを分析し、ほとんどの開発者が Koa のctx.redirect()
方法を使用してオープン リダイレクトを実装していることがわかった場合、最悪の事態を想定するのが妥当かもしれません。GitHubの JavaScript プロジェクトで簡単なコード検索を行いました。ctx.redirect(
16,827 のコード結果が得られました。を検索するcontext.redirect(
と、15,751 件のコードの結果が得られました。これは、分析する 32,578 のコード結果になります。これらの一部は Koa を使用し、一部は Express を使用し、一部は別のものである可能性があります。(もちろん、コンテキストはctx
またはだけでなく、任意の名前で呼び出すcontext
ことができるため、さらに多くのコードを確認することができます。)
問題は、ユーザーが提供したデータを頭を使わずに渡してリダイレクトするのが一般的ですか? 私は、検索条件に一致するすべてのプロジェクトをチェックする小さなスクリプトを作成することで、半自動分析アプローチを採用しました。残念ながら、GitHub がそれ以上のリクエストを拒否したため、最初の 1,000 ヒットを超えることができませんでした。
{
"message":"Only the first 1000 search results are available",
"documentation_url":"https://docs.github.com/v3/search/"
}
これまで見てきたことと、次のセクション (「古い Web ブラウザ」) で説明することを考えると、最悪の場合の実装が合理的であるとは思えません。この特定のケースではありません。
公式のガイダンスには、次のようにも書かれています。
影響を受けるライブラリを使用して特定の実装の脆弱性をスコアリングする場合、その特定の実装についてスコアを再計算する必要があります。
これは合理的であり、状況のサイエンス フィクションの側面をある程度緩和します。これが、脆弱性スコア 9.8 のこの Koa の問題が、私たちのケースでは 0.0 になった理由です。
良いことは、Sonatype が 9.8 の脆弱性スコアが不当であることに同意し、喜んでそれを引き下げたことです。私はそれを感謝しています、そしておそらく他の多くの人もそうするでしょう.
さらに、Sonatype は、システムに問題を追加したとき、顧客がこの潜在的に予期しない状況について知っていることが最善であると信じていたと私に言いました. 彼らは、「私たちが見たものを無視して否定的な結果をもたらす可能性があるよりも、警告する方が良い」と述べました. そしてもちろん、彼らは正しかった。
セキュリティの問題を伝える必要があるかどうかについて、私は一度も疑問を呈しませんでした。はい、セキュリティの問題を可視化する必要があります。私が懸念しているのは、これらの問題がどのように伝えられるかです。
- 何かを脆弱性と呼ぶのは適切ですか、それともセキュリティの弱点または安全でないデフォルトの動作などと呼ぶのが適切ですか?
- 割り当てられた脆弱性スコアは妥当ですか?
- 十分な詳細とコンテキストが提供されていますか?
ここで、古い Web ブラウザーについて少し説明しましょう。
古い Web ブラウザ
Sonatype の優れた人々がいなければ、古い Web ブラウザーについて考えることはなかったでしょう。
今後も古いブラウザは考慮しません。まず第一に、覚えておくべきことが多すぎます。古い Web ブラウザーについて心配することはできません。第二に、古い Web ブラウザ (ユーモアのセンスがない場合はリンクをクリックしないでください!)はどのくらい古いものですか? 「古い」の本当の意味とは?1 年ほど前のブラウザを使用している場合は、すでにXSS よりもはるかに大きな問題を抱えている可能性があります。
それでも、いくつか掘り下げたところ、次のことがわかりました。
- 2016 年からのGoogle Chrome 48.0.2564.109 (64 ビット) (!) は、応答本文さえ表示しませんでした。Koa問題は2018年に発見されたので、2016年までさかのぼれば十分だと思っていましたが、そうではありませんでした。
- 2011 年の Firefox 4.0 では応答本文が表示されましたが、ユーザーは JavaScript ペイロードを実行するためのリンクをクリックする必要がありました。(もちろんリンクです!)
- Koa XSS の問題が報告される 1 年前の 2017 年の Firefox 52.0 では、すでに JavaScript ペイロードを含む応答本文が表示されませんでした。Firefox は、「ネットワーク プロトコル違反」が原因で「破損したコンテンツ エラー」というエラーをスローしました。
Koa 0.0.1 は 2013 年にリリースされたため、この問題が悪用された可能性がある年が数年ありました。この時点で、2018 年の Koa 2.5.0 までは、この問題 (まだ 9.8 スコアではない) にフラグを立てることはおそらく許容されるでしょう。
掘り下げていたら、ウィキペディアで面白いものを見つけました。引用させてください:
Firefox 15 は 2012 年 8 月 28 日にリリースされました … Firefox 15 ではサイレント アップデートが導入されました。これは、ユーザーに通知せずに Firefox を最新バージョンに更新する自動更新であり、[65] Web ブラウザーGoogle ChromeおよびInternet Explorer 8以降が備えている機能です。すでに実装されている
そのため、Koa の最初のバージョンがリリースされる前に、すべての主要な Web ブラウザーに自動更新機能がありました。これは、大多数のユーザーが最新の Web ブラウザーを使用していた可能性があることを意味します。「ビッグバン」の時の様子を見てみましょう:2013年。
- Firefox 15 : 「破損したコンテンツ エラー」というエラーが返されました。これは、応答本文がユーザーに表示されなかったことを意味します。
- Chrome 24.0.1312 (WebKit 537.17) : 応答本文が表示されませんでした。開発者ツールのネットワーク タブを見てみると、ほとんど何も表示されていなかったので、Wireshark を実行して、ブラウザが最初にリクエストを実行したかどうかを確認する必要がありました。Wireshark では、Chrome が PoC サービスにアクセスし、JavaScript ペイロードを含む応答を受信したことがわかりました。応答本文をレンダリングしませんでした。さらに良いことに、何も起こりませんでした。
- Internet Explorer 11 (11.0.9600.19180) : Wireshark を使用して検証した PoC サービスからの応答を取得しました。応答本文がユーザーに表示されませんでした。「このページは表示できません」という古典的な組み込みエラー ページが返されました。
上記の調査を行った後、Sonatype からの引用に戻りましょう。
Koa は、このコンテキストで XSS を気にかけているようです。これは、それを防ぐコードが既にあり、HTML に書き込むときに URL をエンコードする HTML エンティティです。
この記述は正しいですが、Koa の最初のバージョンがリリースされるまでに悪用を許可された主要なブラウザがなかったという事実は、この文が示唆したいこと以外の何か興味深いことを示唆しています。Koa開発者がどのように考えていたのか正確にはわからないため、憶測を書いていることに注意してください. 開発者が最新の Web ブラウザーを使用して問題の動作をテストしたことは容易に想像できます。HTML エンコーディングが適切であることに気付いた可能href
性があります。a
鬼ごっこ。これは深刻な問題を提起します。過去 5 年間をソフトウェア開発側に費やしてきた私にも当てはまります。開発者として、バックエンド側の新しい Web テクノロジを作成しようとしている場合、古い Web ブラウザーを気にする必要がありますか? また、古い Web ブラウザーをどのくらい遡って検討する必要があるかについて、セキュリティ コミュニティからの公式の推奨事項は何ですか? エンド ユーザーのセキュリティのベスト プラクティスは、ブラウザーを最新の状態に保つことであり、自動更新機能もそれを支援するものであると考えるべきではありませんか? また、開発者が古いブラウザーを念頭に置いてテストすることを期待している場合、セキュリティの専門家が同じことを行い、単に「古いブラウザー」?それは公正なことです。
確かなことは、何年も前から心配することは何もないということです…
最新のブラウザ
私の分析では、Web ブラウザーを使用して応答本文を確認したところ、空であることがわかりました。ネットワーク経由で送信された応答に本文があるかどうかは確認しませんでした。応答本文を完全に無視したのは Google Chrome だけであることが判明しました。したがって、表示されませんでした。私にはそれで十分でした。合理的に、私は追加する必要があります。
それ以来、最新バージョンの Koa を使用してテスト Web サービスの応答を調べてきました。以下に、挿入された JavaScript コードを含む HTML 応答本文があったことを確認できます。
* Trying 127.0.0.1:4444...
* Connected to 127.0.0.1 (127.0.0.1) port 4444 (#0)
> GET /?payload=javascript:alert(1); HTTP/1.1
> Host: 127.0.0.1:4444
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Location: javascript:alert(1);
< Content-Type: text/html; charset=utf-8
< Content-Length: 71
< Date: Tue, 22 Nov 2022 17:55:12 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host 127.0.0.1 left intact
Redirecting to <a href="javascript:alert(1);">javascript:alert(1);</a>.
* Trying 127.0.0.1:4444...
* Connected to 127.0.0.1 (127.0.0.1) port 4444 (#0)
> GET /?payload=%22><%2f HTTP/1.1
> Host: 127.0.0.1:4444
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Location: %22%3E%3C/
< Content-Type: text/html; charset=utf-8
< Content-Length: 61
< Date: Tue, 22 Nov 2022 22:18:49 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host 127.0.0.1 left intact
Redirecting to <a href=""></">"></</a>.
今後の変更
以下は、この問題に関して Sonatype が実装を計画している更新プログラムのリストです。
- 誤解を解消するための概要/タイトル行の更新 (既に発生)
- 脆弱性スコアを 4.7 に引き下げる (既に実施済み)
- ユーザーが古いブラウザを実行している場合にのみ脆弱性が悪用される可能性があることに言及してください
私が見たい追加の変更
前のセクションで説明した変更に加えて、さらに改善できる点がいくつかあります。これらは:
- 特に 2018 年以降にリリースされた Koa バージョンの脆弱性スコアをさらに引き下げます。
- 「古いブラウザ」に言及する場合、少なくとも主要な Web ブラウザのバージョン番号とそのリリース日をレポートに含めます。これは、「影響を受けるライブラリを使用して特定の実装の脆弱性を評価する」ときに、誰にとっても非常に役立ちます。たとえば、ユーザーが 2011 年以降のブラウザーを使用する必要があることを確認した場合、SCA で 1 秒以内にその問題を「影響を受けていない」とマークしたでしょう。多くの時間を節約できます。
- 影響を受ける Koa のバージョンは、脆弱性のページに記載されています。
ところで、Sonatype はまた、商用製品にいくつかのクールなチェックがあることにも言及しました。たとえば、コード レベルで実際のチェックを実行して、アプリケーションが報告された脆弱性の影響を受けているかどうかを確認します。ライブラリの脆弱性スコアがどのように計算されるかというサイエンスフィクションの性質を考えると、特にこのような状況が続く場合、エンジニアリングチームの負荷を軽減するために、これらの種類のチェックは必須です.
結論
それは私が持っているほとんどすべての更新です。とてもプロフェッショナルでフレンドリーなソナタイプに連絡をとってよかったです。彼らと一緒に仕事ができて光栄でした。
Koa の XSS について: これは、ここ数年、誰も心配する必要がなかったものです。