web-dev-qa-db-ja.com

オープンソースに関連する信頼の問題

ごく最近、私が検討していなかった問題に2つの個別の議論が浮かびました。使用しているオープンソースバイナリを確認する方法は、公開されているソースコードに基づいています。

LeastAuthority.comの創設者兼CEOであるZooko Wilcox-O'Hearnのサイレントサークルの主な2人であるPhil ZimmermannとJon Callasへの公開書簡に基づく、暗号化ランダムビットに関する大規模な議論 スレッド があります。 、主題に触れたサイレントメールを運営している会社。さらに、本日公開されたDr. Dobbsの記事 Putting Absolutely Everything in Version Control にも触れました。

この質問で懸念される問題は、オープンソースコードを再コンパイルして、公開されたバイナリと同じ結果を得る機能です。つまり、同じバイナリを再作成してソースコードからハッシュした場合、ツールチェーンの違いやコンパイラ自体のランダム化のために、同じバイナリである可能性はほとんどありません。

ドブス博士の記事では、再現性の理由から、ツールチェーンでさえバージョン管理下に置くことを推奨しています。 Jon Callasは、多くの場合、ライセンス制限を含むさまざまな理由により、ツールチェーンを再配布することが不可能である可能性があると指摘しています。自分でコードをコンパイルしていない限り、バイナリを他のユーザーが再作成することさえできず、同じ結果で信頼セットを仮定セットに追加することになります。

これは当然のことながら受け入れられているリスクであることを理解しています。私の質問は、コンパイル時にソースコードをバイトごとに再現可能にすることに関して、オープンソースバイナリのプロバイダーさえも信頼する必要性をなくすことに関する他の議論や指標はありますか? Jon Callasの議論で言及されているように、Ken Thompsonは 「自分で作成したのではないコードを信頼することはできません。」 この問題に関するセキュリティ上の意味は何ですか?

15
zedman9991

ソースコードを再コンパイルして独自のバイナリを作成できる場合は、配布されているものとまったく同じバイナリを取得できない可能性があります。しかし、なぜそれが問題になるのでしょうか?その時点で、あなたは自分のバイナリを持っているが、ソースコードと必ず一致します(コンパイラ自体が悪意のあるものではないと仮定します)。バイナリパッケージを破棄して、独自のバイナリを使用できます。バイナリ。

言い換えれば、コンパイル出力を検証できる状況は、自分でコンパイルできる状況であり、検証を論議の的としています。

バイナリパッケージではなく、ソースコードの配布とローカルコンパイルに依存するパッケージ配布フレームワークが世の中に存在します。例えば pkgsrc (NetBSDのネイティブシステム)または MacPorts (MacOS Xマシンの場合)。ただし、信頼やセキュリティのためにこれを行うわけではありませんが、バイナリパッケージの配布にはビルドシステムが含まれているため、これらは無料ではありません。また、pkgsrcの1つのポイントは、ローカルコンパイルオプションの簡単な管理を提供することです。

有名なトンプソンのエッセイは、自分でコンピレーションを作成するだけでは不十分であるという考えを強調しています。極端に言えば、独自のコードだけでなく独自のコンパイラも記述し、それを自分で設計して刻印したハードウェアで実行する必要があります。砂のバケット( silicon 、半導体の主成分)。もちろん、これはかなり 非実用的 です。したがって、2番目に優れたものが必要であり、2番目に優れたものはパラダイムシフトです:信頼を暴力に置き換えます

バイナリパッケージは signed です。パッケージインストーラーはインストール前に署名を検証し、「信頼できるソース」からのものではないパッケージを拒否します。同じ概念が Javaアプレット にも当てはまります。署名されていれば、追加のアクセス許可(実際には、コンピューターで何でもできるアクセス許可)を付与できます。これは実際には署名ではなく、単なる認証であることに注意してください。パッケージが「信頼できるリポジトリ」からHTTPS経由でダウンロードされただけでは十分ではありません(実際に必要でもありません)。このようなダウンロードにより、パッケージが信頼できる人からのものであり、転送中に変更されていないことがかなり保証されます。しかし、あなたはもっと欲しい:証明が欲しい。パッケージがマルウェアで一杯であることが判明した場合、署名を使用します。その場合、署名を使用して、パッケージプロバイダーが少なくとも「過失によって」共犯者であることを証明できます。署名にはresponsibilityがあり、責任はfearに作用します。虐待された顧客からの訴訟の恐れ。法執行機関からの報復に対する恐怖。最終的には、暴力への恐れ。

13
Tom Leek

それはそれほど単純ではありません。

プログラムを構築できるプラットフォームが非常に多いため、元のビルド環境を複製することは非常に困難な場合があります。このため、異なるバージョンのライブラリを使用して、異なる設定の異なるコンパイラを使用している可能性があります。環境におけるこれらのわずかな変動は、コンパイルされたバイナリに確実に影響を与える可能性があります。もちろん、作成者がビルド環境を正確に指定する用意がある場合、または運が良ければ(異なる言語がこれに影響を与える可能性があります)、まったく同じバイナリを再ビルドすることもできます。

これが問題であった最近の状況については、オープンソース風のTrueCryptを参照してください フルディスク暗号化プログラム。 TrueCryptサイトが突然TrueCryptプロジェクトの予期しない終了を宣言するアナウンスに置き換えられたとき、人々は明らかにコードをチェックすることに興味を持っていました。ただし、TrueCryptをビルドするさまざまな人々が、ビルド環境のバリエーションのために、公式のビルドとは大きく異なるバイナリを取得することがよくありました。 1人 どうやら(元の環境に非常に近いものを再作成するという困難な作業の後で)コンパイルされた出力のわずかな変化のみでTrueCryptビルドを最初から複製するように管理されています。1 もちろん、同じことをしようとしない限り、自分でこれを確認することはできません。

そのページで興味深いのは、バイナリにコンパイル時のタイムスタンプが含まれていることです。これだけでは、ハッシュのコンパイルと比較は機能しません。

0:TrueCryptには奇妙なライセンスがあり、いくつかの問題があります。プロジェクトをforkすることが実際に安全かどうかは定かではありません。

1:実際、TrueCryptサイトの奇妙な前に彼らがこれを行ったように見えますが、それ以降、バージョン7.2ビルドの複製にも成功しました。

24
Lily Chung

コードを自分でコンパイルすると、同じバイナリがmay取得されます。か否か。基本的に、コンパイラーが決定論的最適化アルゴリズムを使用している場合(これは通常のケースです)および同じコマンドラインオプションを使用してまったく同じコンパイラーバージョンを使用する場合(通常は多くの場合)確保するのが難しい)。

確定的な再コンパイルは、「コンパイルされた」フォーマットが正式に指定されており、実際には最適化されていないプログラミングフレームワークを使用すると簡単になります。 Javaバイトコードまたは.NETアセンブリについてここで話しています。そのようなツールを使用する場合、ソースコードを再コンパイルして同じバイナリを取得することは可能です、難しいですが、CまたはC++では忘れてください。

通常の方法は次のとおりです:

  • 自分をコンパイルします。
  • 信頼できるサードパーティにコンパイルを依頼してください。そのサードパーティはソースのコピーを取得し、自分のマシンからコンパイルを実行し、sign(暗号化または紙を使用)でソースアーカイブと生成されたバイナリの両方を取得します。
  • バイナリのプロバイダーにバイナリの署名を依頼し、リバースエンジニアリングは必要に応じて不正行為を実証するのに十分実行可能であることを信頼してください(これも、Javaバイトコードよりもはるかに妥当ではありません)コンパイルされたCコード)。
  • 外部ソフトウェアを使用しないでください。すべてを社内で再実装します(そうです、これは通常のメソッドであり、recommendedとは異なります)。
  • 幸運を信じてください(確かに推奨される方法ではありませんが、短期的には最も安い方法です)。

また、コードを(再)コンパイルするには、コンパイルが行われるマシンが敵意のある制御下にないことが必要です。この 非常に古典的なエッセイ は、主題に関して必読です。根底にある考え方は、信頼がどこか(ハードウェア自体のみで、ファームウェアがマルウェアのないものと想定されている場合)から開始する必要があるということです。明確な監査証跡を維持する。このようなトレースは、バックドアの挿入を保証するものではありませんが、問題が発生した場合の責任と責任の割り当てに大きく役立ちます。

16
Thomas Pornin

はい可能です。しかし、コンパイルプロセス全体がその目的のために設計されていないため、それは非常に困難です。これはしばしば「確定的ビルド」、「再現可能なビルド」、「べき等ビルド」と呼ばれ、課題です。

ビットコイン、 Tor 、および Debian は、決定論的ビルドを使用しようと試みており、技術的なプロセスは here で説明されています。

確かに、このプロセスは不完全で壊れやすく、正しく行うのが非常に困難です。クロスプラットフォームのビルドを検討すると、問題はさらに複雑になります。

11

私は決定論が好きです。

コンパイラやソフトウェアツールは、実際には不正な数学的変換です。 s(ソースコード)を受け取り、関数C()に入れて、バイナリ出力bを生成します。

b = C(s)毎回!そうでなければ、決定論は失敗し、私たちは皆気が狂います。

つまり、同じsと同じC()から始める限り、常に同じbが生成されます。

そして、これは、bまたはH(b)のハッシュを実行して、他の誰かのH(b)と比較して、バイナリは私たちが期待するものです。

そして、変更が発生します。sがs 'に変更され、C()がC'()に変更されます。大野!

C(s) = b1およびC '(s)= b2およびC(s')= b3およびC '(s')= b4であるため

もちろん、H(b1)、H(b2)、H(b3)、またはH(b4)の2つは一致しません。

そして問題は、バイナリbを生成するために必要なコンポーネント(ツールチェーン、環境、構成、OSなど)がより多く、相互依存的になるにつれて、同じbを再現することがますます難しくなるということです。

待って、まったく同じbが必要なかったとしたら?

次に、bとb '、およびそれらの違いを扱います。

参照バイナリbと生成されたバイナリb 'の違いを見つけ、その違いの意味を調べるために必要なことはすべてです。 bとb 'のソースがsの場合は、C()とC'を扱っていることを意味します。したがって、C()とC '()の違いをbとb'の違いに関連付けることができます。したがって、bを正確に再現できない場合でも、C()の代わりにC '()を使用することで、原因の違いを明らかにすることにより、b'にある程度の信頼を得ることができます。

3
this.josh

同じソース、同じOS、同じライブラリ、同じコンパイラ、同じローダーを使用しても、コンパイルおよびロード操作の日付に関する情報が含まれているため、2つのバイナリは一致しません。

まったく同じシステムと開発環境で、同じバイナリを2回ビルドすると、異なるバイナリになるため、ハッシュも異なります。

 $ md5 nmap 
 MD5(nmap)= 8ef4b7c1cb2c96ce68d9e08224419b4f 
 $#make clean、make install 
 $ md5 nmap 
 MD5(nmap)= 94467bc5397351f245929f3 

一方、シンボルテーブルが削除されなかった場合、これらのシンボルテーブルは一致し、バイナリが特定のソースから実際に構築されていることを診断するための適切な近似になります。

 $ nm -a nmap> /tmp/nmap.nm.1 
 $#クリーンにしてインストールを作成
 $ nm -a nmap> /tmp/nmap.nm.2 
 $ diff /tmp/nmap.nm.[12]
$

これは、バイナリが実際にツリーソースの特定のバージョンからのものであることを確認する場合にのみ有効です。すべてを調整する外部ソースが疑われる場合は、これらのシンボルテーブルでさえ「配置」される可能性があります。

3
dan

一般に、他の誰かの編集を信頼できるかどうかわからない場合は、自分で編集するか、信頼できる人からそれを入手する人を見つけるように努力します。

しかし、あなたのコンパイラが感染していないことを信頼できますか?

亀はずっと下にいます。ある時点で、常に判断を下す必要が生じたり、ウイルスチェッカー、ファイアウォール、その他のセキュリティシステムに依存したりすることになります。

AFTERTHOUGHT-これは、オープンソースコードの製品版を配布する企業が存在する理由の1つです。彼らはコードベースを監視し、ビルドがクリーンであることを約束し、(購入した場合)継続的なサポートを提供します。ストールマンのGNU manefestoでさえ、「ソフトウェアは無料である必要があり、サポートには費用がかかるはずです」と述べました。

ダウンロードを信頼できる状態に保つことは、サポートの一種です。あなたはかもしれませんが無料のコミュニティから良いサポートを受けることができます...しかし、それにいくらかお金をかければより良いサポートを受けることができます。ご希望のトレードオフポイントを選択してください。

セカンダリマシンをハッキングするために、ランダムなLinuxビルドを使用したいと思っています。私が実際に依存しているパーソナルマシンには、Fedoraのようなものを使用したいと思います。そして、もし私がそれにビジネスを賭けていたら、私は完全に購入した製品バージョンであるRed Hat Enterpriseまたはそれに似たものを使います。 (推奨は示唆されていません。FedoraとRHELは、1つの会社がその範囲の2つの異なる点に対処する方法を示す良い例にすぎません。)

3
keshlam

バイナリで信頼している基本的なことの1つは、バイナリを取得した場所です。 sourceforgeやdownload.com、またはウイルスがなく、それで十分だと言っている人なら、それを試してください。あなたは彼らの言葉をそれに取っています。

バイナリを信頼したくない場合、他の唯一の本当の答えは、ソースコードからコンパイルすることです。 Java実行可能なバイトコード、またはjarのようなもの、またはORバイナリに至るまで。

独自のバイナリをコンパイルする場合、はい、標準バイナリと同じものになってしまう可能性があります(すべてが同じであり、ビットが少し一致することを意味します)。あなたはたまたま同じハードウェアを実行していて、同じプロセッサ用にコンパイルしていて、コードのコピーに余分な改行を誤って残していない人はいない... (少なくとも)読む能力があった。 C++を知らず、コードを吟味した他の人を信用していない場合は、難しいでしょう。 C++を学び、自分で吟味してください。

つまり、すべてが完全に一致しない限り、バイナリを検証することはできません。ただし、オープンソースコードはいつでも確認できます。時間をかけるか、おそらく誰かが行ったと思われる分析を信頼するかどうかは、あなたの選択です。

1
PsychoData