N-Day 脆弱性の範囲を理解するためのオープンソース インテリジェンス

ゼロデイ脆弱性は、サイバー犯罪者にとって聖杯のようなものです。しかし、N-day脆弱性は、発見から数年経過しても問題を引き起こす可能性があります。ターゲットが脆弱である場合、その脆弱性が未知であるか、何十年も前から知られていたかは問題ではありません。しかし、N-day脆弱性は、発見から数年経った後でも問題となる可能性があります。N-daysは常に新しいプロジェクトに入り込み、その危険性を永続させています。残念ながら、オープンソースソフトウェア(OSS)もパッチの適用を受けていないN-daysに悩まされることがあります。これは、コードの再利用や保守者のリソース不足が一因です。クローズドソースソフトウェアとは異なり、オープンソースソフトウェアのリポジトリはオンラインで利用可能であり、大量偵察の手段を提供します。N-day問題がどれほど大きなものになるかを理解するために、ここここの記事のPython tarfileの調査をケーススタディとして使ってみましょう。

今年初め、Kasimir Schulzは、別のプロジェクトのための調査中に、ディレクトリトラバーサルの脆弱性を発見しました。彼は、開発者が自分のコードにこの脆弱性を不注意に含めることが容易であることに注目しました。さらに分析を進めると、これは2007年に公開されたPythonのtarfileパッケージにおける15年前のNday脆弱性であるCVE-2007-4559の結果であることが判明しました。彼が注目したのは、この問題が単純であることです。実際の脆弱性は、サニタイズされていない、tarfile.extract()やtarfile.extractall()の組み込みデフォルトを使った2〜3行のコードから発生します。

     myfile.extractall()

tarfile.extract() や tarfile.extractall() を呼び出す前にメンバーファイルをサニタイズする安全なコードを書かなかった場合、ディレクトリトラバーサルの脆弱性が生じ、悪意のある者がファイルシステムにアクセスできるようになります。確かに、これは一過性のものでした。

この脆弱性は10年以上前から知られていただけでなく、Pythonの公式ドキュメントでは、ディレクトリトラバーサルの問題から、「信頼できないソースからアーカイブを事前検査なしに展開しないこと」と明確に警告しています。しかし、私たちは確かめたいと思いました。公式ドキュメントが、この問題について警告していることはすでに知っていますが、多くの開発者は検索エンジンやStack OverflowなどのWebサイトに助けを求めています。How to extract tarfile in Python “で検索したところ、extract()やextractall()の危険性についての議論がないことがわかりました。特に「Securely extracting tarfile in Python」で検索して初めて、Stack Overflowで有意義な議論を見つけることができました。これは良い兆候ではないので、私たちはこの問題がどの程度広まっているかを確認するために、実際のコードを見てみることにしました。

クローズドソースのソフトウェアは、一般的に入手も検査も難しいため、代替手段としてOSSを調査することにしました。OSSのリポジトリを探すのに適しているのは、マイクロソフトが所有するGitHubです。GitHubには8,300万人以上の開発者がおり、2億以上のリポジトリが公開されています。まず最初に必要なことは、潜在的な問題の範囲を把握することです。まず、tarfileを使用してすべてのPythonプロジェクトを見つけることから始めます。単に tarfile を検索すると、100万件の結果が得られますが、その多くは関連性がないように見えます。もっと高度な検索が必要です。幸いなことに、GitHub は高度な検索機能を提供しています。詳細検索を使って、以下の検索文字列で30万件強に範囲を絞り込みました。

    “Import tarfile” language:Python

“import tarfile “は、tarfileクラスを使用するために使用しなければならないので、プロジェクトがコードの中でtarファイルを管理しているかどうかの良い指標になります。”extract() “や “extractall() “を使うと他のライブラリからの誤検出が多くなり、”tarfile.extract() “や “tarfile.extractall() “を使うと逆に誤検出が多くなりすぎてしまいます。language:Pythonは、Pythonのファイルだけが考慮され、tarfileを参照しているかもしれない、テキストドキュメントのような他のファイルは考慮されないことを保証することによって、さらにこれを改善します。これは300k以上のファイルが脆弱であるという意味ではなく、単にtarfileパッケージを使用しているPythonファイルであるという意味です。さて、ここでのタスクは、tarfile.extract() や tarfile.extractall() が、 tar メンバーの適切なサニタイズを行っていないものを探すことです。これは高度な検索ではできないので、レポのサンプリングという基本的な統計手法に戻しました。この方法は、検索からリポジトリの名前をスクレイピングし、Bashスクリプトを実行してローカル処理のためにそれぞれのリポジトリをクローンするものでした。

 for str in ${arr[@]}; do
 git clone https://github.com/$str.git
 done

arrという変数には、スクレイピングしたすべての名前のリストが格納されており、合計で257の名前から、より大きな母集団を統計的に測定することができます。この小さなスクリプトは、各リポジトリをローカルドライブにダウンロードし、より簡単に分析を自動化できるようにします。まず、175のリポジトリを手動で調べ、”extract() “または “extractall() “を含むかどうか、そして事前にtarfileメンバーのクリーンアップを行っているかどうかを確認しました。その結果、61%のリポジトリがそうなっておらず、これらのリポジトリは脆弱であり、悪用される可能性があることがわかりました。すべてのサンプルを網羅するために、私たちはCreosoteというPythonツールを作成し、ダウンロードした257のリポジトリすべてで実行しました。Creosoteは基本的に、プログラマーがFile Openの直後にextractall()を呼び出したかどうか、あるいはサニタイズ処理なしに個々のファイルを取り出したかどうかをチェックします。私たちが手作業で行った調査と同様、半数以上、正確には65%が脆弱性を抱えていました。残念ながら、今回の発見は一過性のものではなく、より大きな問題の指標となるものでした。もし私たちのサンプルがより大きな集団とよく相関するならば、この脆弱性のインスタンスは20万件弱あり、GitHub上に存在していることになります。しかし、私たちはより正確で完全な推定値を知りたいと思いました。私たちはGitHubに連絡を取り、調査を手伝ってもらうことにしました。GitHubの協力により、Pythonコードに「import tarfile」を含むユニークなリポジトリ588,840件を含む、より大きなデータセットを取得することができました。手動で計算した61%の脆弱性率を使用すると、現在、35万以上のリポジトリが脆弱であると推定されます。

この大量の脆弱なコードは、いくつかの不幸な副作用を示しています。コードそのものだけでなく、プログラマーの作業を高速化するための新しいツールも生まれています。GitHub Copilotは、機械学習を使ってGitHub上のコードを分析し、プログラマーのための「オートコンプリート」の一形態を作り出す、そうしたツールの1つです。データサイエンスの世界では、「Garbage in garbage out(ゴミを入れたら、ゴミが出てくる)」という言葉があります。tarfile.extract()やtarfile.extractall()の30万件の誤ったインスタンスにより、これらの機械学習ツールは安全でないやり方を学習しています。ツールのせいではなく、他の人たちから学習したという事実が原因なのです。図1は、GitHub Copilotがtar.extractall()を「自動完成」させた様子を示しています。灰色の提案文は有効な抽出手順を書いていますが、事前にtarfileをサニタイズすることに失敗していることに注目してください。

図 1: GitHub Copilot は、脆弱な tarfile 抽出コードをオートコンプリートします。      
図1: GitHub Copilot は、脆弱な tarfile 抽出コードをオートコンプリートする

私たちが安全を確保するためには、誰かがこれをどうにかしなければなりません。それは、私たちから始めた方がいいかもしれません。588,840のリポジトリを分析し、300,000以上のパッチを適用するために、新しい自動化ツールを構築する必要がありました。Python、Bash、Creosote、そしてGitHub APIを組み合わせて、私たちは以下のようなプロセスの多くを自動化することができました。

  • Mass Repository Forking
  • Mass Repository Cloning
  • Code Analysis
  • Code Patching
  • Code Commits
  • Pull Requests

当社のツールを使って、現在11,005のリポジトリに対するパッチがあり、プルリクエストができる状態になっています。各パッチはフォークされたリポジトリに追加され、時間をかけてプルリクエストされる予定です。これにより、個人でも組織でも、問題を認識し、ワンクリックで修正できるようになります。脆弱性のあるプロジェクトの規模が大きいため、今後数週間にわたってこのプロセスを継続する予定です。これは全脆弱なプロジェクトの12.06%に当たる見込みで、完了する頃には7万プロジェクト強になります。これは大きな数字ですが、決して100%ではありませんし、すべてのプルリクエストはプロジェクトの保守者が受け入れなければなりません。業界として、私たちはまだやるべきことがたくさんあるのです。

私たちは可能な限り多くのリポジトリを修正しますが、全体の問題を解決することはできません。私たちが発見した脆弱性のあるリポジトリの数は、他にどのようなNday脆弱性がOSSに潜んでいて、何年も発見されなかったり無視されたりしているのかという疑問を抱かせます。tarfileのディレクトリトラバーサル脆弱性は、2007年から知られているだけでなく、公式ドキュメントで明確に警告されています。それにもかかわらず、サンプルの61%が、この脆弱性を安全に実装していません。この脆弱性に対して、私たちは多くの努力をしてきましたが、本当の解決策は、問題の根源に取り組むことです。つまり、オープンソースのコードに対する熱心なセキュリティ評価と、タイムリーなパッチ適用です。N-daysは年単位ではなく、日単位で測定されるべきです。私たちは、OSSを監査するためのデューディリジェンスを確実に行い、脆弱なコードを野放しにして悪用されることのないようにする必要があるのです。今回のtarfileの脆弱性が指標となるならば、私たちは非常に遅れており、OSSの安全性を確保するための取り組みを強化する必要があります。

※本ページの内容は2022年9月21日(US時間)更新の以下のTrellix Storiesの内容です。
原文: Open-Source Intelligence to Understand the Scope of N-Day Vulnerabilities
著者: Charles McFarland