Skip to main content

脆弱性開示の舞台裏:Zip Slip脆弱性

Public Disclosure of Critical Arbitrary File Overwrite Vulnerability Zip Slip

2018年8月15日

0 分で読めます

2018年6月、Snykの調査チームは、さまざまなエコシステムで数千ものアプリケーションに影響するZip Slip脆弱性の悪用可能な事例を多数発見しました。このように広範囲に及ぶ脆弱性については、公開前に脆弱なライブラリやプロジェクトへリスクを知らせる、綿密に計画された非公開の開示プロセスが必要です。しかし、世間に知られることなく、これほど多くの対象について脆弱性を発見し、修正し、開示するにはどうすればよいのでしょうか。この記事では、発見から開示、修正PRの作成、その後の対応まで、私たちがどのように進めたのかを詳しく紹介します。

Zip Slipは、特定のパッケージやライブラリに固有の脆弱性ではなく、多くのプロジェクトで非常に広く見られる任意ファイル書き込み脆弱性の一種です。また、Zip Slipは厳密には新しい脆弱性ではありません。この種の脆弱性は何年も、場合によっては何十年も前から存在していました。しかし、広く見られること、そしてセキュリティチームが脆弱な事例を多数発見したことから、Zip Bomb脆弱性と同様に、名称を付けるべきだと考えました。

始まり

始まりから振り返ってみましょう。2018年初頭、継続的な調査の一環で、私たちはFTPクライアントがフォルダーをダウンロードする際の脆弱なパターンを特定し、Apache Hiveで悪用可能な実装を発見しました。これは、1990年(それ以前も)にFTPクライアントで見つかっていた既知の脆弱性が、さまざまなプログラミング言語のオープンソースFTPクライアントライブラリに今も存在することを示しています。その後も、広く使われているオープンソースライブラリで同様のパターンを探しました。

まずはアーカイブの展開処理から調べることにしました。アーカイブからファイルを展開する際、ディレクトリトラバーサルを可能にする攻撃経路が存在する場合があります。ディレクトリトラバーサル脆弱性では、攻撃者が本来対象フォルダー内にあるべきファイルシステムの領域を越えてアクセスできます。さらに、実行ファイルを上書きし、それをリモートから実行したり、システムやユーザーが実行するのを待ったりすることで、被害者のマシン上でリモートコード実行を実現できます。設定ファイルなどの機密リソースを上書きして被害を与えることも可能で、クライアント(ユーザー)のマシンとサーバーの両方が攻撃対象になります。

アーカイブ内のエントリと、/tmp/evil.shへのパストラバーサルを示すターミナル出力

悪用可能なライブラリを探す

チームは、Java、JavaScript、Goの各エコシステムで人気のあるオープンソースライブラリから、複数のコードサンプルを調べ始めました。ほどなくして、驚いたことに、半数以上に脆弱性があると判明しました。これは、最初に調査したライブラリの半数以上が、アーカイブ内のファイル名をサニタイズも検証もしておらず、悪用されると任意のファイルを上書きされる可能性があることを意味します。全リストはこちらでご覧いただけます。

早い段階で、この脆弱性の影響はプログラミング言語によって大きく異なり、ほとんど見られない言語もあることが明らかになりました。アーカイブ管理機能を提供する方法の違いによって、Zip Slip脆弱性の広がり方がどう変わるのか、いくつかのエコシステムを見てみましょう。

JavaにおけるZip Slip

たとえばJavaのランタイムは、コア言語の一部としてZipクラスを提供しており、アーカイブの読み込みやZIPアーカイブからのファイル展開を行うコードを開発者が記述できます。Apache Commons-Compressなどの人気Javaライブラリは、ほかの形式にも対応しているため問題の範囲はさらに広がります。しかし、1回の呼び出しで処理を完結できるシンプルなAPIがないため、エコシステム内でさまざまな実装が生まれ、その大半に脆弱性がありました。

PythonにおけるZip Slip

一方、Pythonはコアランタイムが提供するzipfileクラス((zipfile.extractall()))を備えており、脆弱ではありません。そのため、Pythonのリポジトリを分析する中で、安全な実装を次々と見つけました。

なお、Pythonのtarfileは依然として影響を受けます。これは、コアランタイムの実装に脆弱性があるためです。ライブラリではなく言語のコアランタイムに脆弱性がある場合、アプリケーションや依存関係を変更しなくても、言語を新しいバージョンにアップグレードする際に自動的に修正が適用されることがあります。開発者が依存関係を新しいバージョンにアップグレードするよりも、こちらのほうがよくあるケースです。もちろん、Snykのようなツールを使っている場合は別ですが!(露骨な宣伝をせずにはいられませんでした!)

ほかに影響を受けるのは?

この時点で、主要な言語やライブラリの一部が深刻な影響を受けていることがすぐに分かりました。そこで、ライブラリではないオープンソースプロジェクトに注目することにしました。GitHubで公開されている、アーカイブ操作コードを含む人気のJavaオープンソースプロジェクトをスキャンしました。

大半の実装に脆弱性があることがすぐに分かりました。特にJavaでよく見られ、同じ脆弱な実装が繰り返し使われていました。こうした脆弱なコード片が、ほかのプロジェクトやドキュメント、コミュニティから流用されていることがうかがえました。

StackOverflow:脆弱性の温床

開発者がコードをコピー&ペーストする際に利用する最大のリソースを分析すると、私たちの仮説が正しいことはすぐに明らかになりました。アーカイブからプログラムでファイルを展開する最適な方法を尋ねる質問が多数見つかりました。さらに、StackOverflowの回答のほぼすべてに脆弱性がありました。最も懸念されたのは、脆弱な回答がどれも、数えきれないほどの賛成票を集めていたことです。気分を明るくしてくれたコメントもいくつか含め、お気に入りを紹介します。

非公開での開示を開始した後も、セキュリティチームは調査を続け、さらに多くの脆弱性事例を発見しました。判明したことを、主な数字でまとめます。

  • 脆弱なライブラリは12件。修正PRを5件作成し、マージされました。

  • 5つのライブラリには、高レベルAPIがありませんでした。

  • 脆弱な実装を含むアプリは数千件(必ずしも悪用可能とは限りません)

興奮するのは悪いこと?

セキュリティ研究者の役割は、脆弱性を発見してセキュリティ上の欠陥を修正し、毎秒成功する重要なビジネストランザクションを何十億もの人々が安心して信頼できる、安全なソフトウェアの世界を築くことです。だからといって、重大な脆弱性を見つけたときに喜びを感じてはいけないわけではありません。仕事の中で時折訪れる「分かった!」という瞬間が、気持ちの高揚しない時期も精度を重視して取り組む原動力になります。興味深い発見や脆弱性がすぐそこにあるかもしれないと思えることが、何日も、何週間も、何か月も調査を続けるモチベーションになります。脆弱性を発見したときの喜びは、開発者が複雑なバグの根本原因を突き止めたときや、アプリケーションを再設計してパフォーマンスを2倍に、スケーラビリティを3倍に向上させたときの達成感に似ています。

大規模プロジェクトで初めてZip Slip脆弱性を発見したときは、とても興奮しました。私たちにとっての「分かった!」という瞬間でした。しかし、ほかのあらゆるアプリケーションにも脆弱な実装があると判明したときは、非常に驚きました。この脆弱性の影響が一部のアプリにとどまらず、さまざまなエコシステムの多数のプロジェクトに及んでいると気づかされたのです。

データをくまなく調べ、特定の言語がより大きな影響を受ける理由や、脆弱なコード片がオープンソースプロジェクト間でどのように広がるのかを理解することは、とても刺激的で多くの気づきがありました。また、脆弱性探しとはまったく異なる種類の調査でもありました。本当に大変な作業は、開示してプロジェクトが脆弱なコードを修正できるよう支援するところから始まりました。弱点を1つ見つけるのは比較的簡単ですが、すべてのつながりを強化するのは困難です。

開示

責任ある開示プロセスに従い、一般公開日を6月5日に設定しました。これにより、プロジェクトのメンテナーには問題を修正するための60日間が与えられました。発見したプロジェクトはすべてオープンソースだったため、コミットやプルリクエストなど、リポジトリ上の活動も公開され、誰でも確認できます。そのため、修正に妥当な期間を設けることと、未修正のプロジェクトを危険にさらすような広範な情報公開のリスクとのバランスを取ることが重要でした。

最初に、脆弱性を含む広く利用されているライブラリのメンテナーに連絡し、問題を知らせました。最初のメールでは合計10件に連絡しました。中には、自分のために作ったライブラリが、最も人気のある展開ライブラリの1つになっていたことさえ知らない人もいました。10のライブラリのうち5つのメンテナーから修正の支援を求められたため、私たちは修正プルリクエストを作成しました(plexus archiver、mholt/archiver、adm-zip、unzipper、zip4j)。

意図したディレクトリの外にファイルを展開するZip Slip脆弱性について説明するGitHubのプルリクエストと、Javaコードの例。

ライブラリのメンテナーへの連絡後、共通ライブラリを使わず独自の展開処理を実装していた、影響を受けるプロジェクトにも対応を進めました。このコードは一から実装されたか、ドキュメントやStackOverflow、ほかのOSSプロジェクトからコピー&ペーストされた可能性があります。いずれの場合も、脆弱なコードが広く共有される結果になりかねません。リストを作成してみると、修正による情報漏えいや、影響を理解しない無責任な人が情報を共有するリスクを避けながら、すべてに連絡するのは難しいほど対象が多いことが分かりました。まずは主要なプロジェクトに絞り、脆弱な実装を含むプロジェクトが15件あったApacheから対応を始めました。

Apache Software Foundationの創設メンバーでApacheのセキュリティ責任者を務めるMark J Coxとの電話会議の後、影響を受けている可能性のあるすべてのプロジェクトをまとめた共同編集のスプレッドシートを作成しました。Apache側でトリアージし、悪用可能かどうかを判断するためです。悪用可能かどうかにかかわらず、脆弱な実装を修正するのはよい慣行です。将来悪用されたり、ほかのプロジェクトにコピー&ペーストされたりするリスクがあるため、ほぼすべてが修正されました。Apache Hadoop、Storm、Hive、Maven、Antが影響を受けていることが判明し、一般公開時に公開CVE(CVE-2018-8008、CVE-2018-8009)が発行されたほか、ApacheサイトでMaven Zip Slipに関する告知も公開されました。Markは非常に協力的で、影響を受けたApacheプロジェクトごとに、問題の特定、修正、周知を進めるうえで力を貸してくれました。

Pivotal(zip統合。開示から2日以内に修正!)、Oracle、Google、OWASP Dependency-Check(開示から1日以内に修正!)など、ほかにも多くの関係者に連絡しました。

最後に、影響を受けた他のすべてのプロジェクトに非公開で情報を開示することにしました。プロジェクトの数が多く、1つのチームだけで手作業によるテストとトリアージを行うのは難しかったため、メンテナーに潜在的なリスクを知らせ、プロジェクトが実際に悪用可能かどうかを各自で確認してもらうプロセスを自動化しました。もちろん、このような大規模な一括開示には、情報が公になるリスクも伴います。脆弱性のないプロジェクトの1つがTwitterに投稿したため、投稿を削除してもらうために非公開で追加のやり取りが必要になりました。

公開後に行ったこと

問題が公になった際、脆弱なコード例や推奨される修正方法などを掲載した情報提供ページを公開しました。また、影響を受けるライブラリやプロジェクトをコミュニティが確認でき、対象外だった新しいライブラリやプロジェクトを追加して情報を共有できる共同GitHubリポジトリも作成しました。先月には、closure、sharpziplib、quazipなど、複数のライブラリやプロジェクトが追加されました。

Zip Slipの情報開示について詳しく知りたい方、情報開示に関するアドバイスが必要な方、またはSnykによる非公開での情報開示支援をご希望の方は、security@snyk.ioまでお問い合わせください。オープンソースをより安全にするために、コミット一つひとつから喜んでお手伝いします。

Capture the Flagを始めよう

オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。

カテゴリー: