web-dev-qa-db-ja.com

ランダムな見知らぬ人からのソースコードをコンパイルすることはどのくらい安全ですか?

求職者がスキルを証明するために送信するコードを確認しているとします。明らかに、私は彼らが送信する実行可能ファイルを実行したくありません。それほどはっきりしていませんが、コードのコンパイル結果を実行したくないのです(たとえば、 Javaでは、実行可能なコードをコメントに隠すことができます )。

彼らのコードをコンパイルするのはどうですか?コンパイラの警告がある場合は警告しますが、コードにコンパイラを悪用する巧妙な文字シーケンスが含まれていて、コンパイラがマシンを危険にさらしている場合はどうなりますか?

私が「コンパイラの脆弱性」をググると、コンパイラの最適化とコードの放出、および放出されたコードが元のソースコードと同じくらい安全かどうかがわかります。

コンパイラーは通常、いくつかの巧妙なコードをコンパイルするときにユーザーマシンを危険にさらさないように検証されていますか?見知らぬ人からのコードをコンパイルするのはどのくらい安全ですか?

41
sharptooth

場合によります。

このmakefileは、ホームディレクトリを削除する可能性があります。

all:
    rm -rf ~

したがって、cmakeやmakefileシステムなどのツールを使用する必要がある場合は、安全ではありません。それは、コーダーがどれほど悪意があるかに依存します。

一方、コンパイラは人がプログラムするため、バグが発生します。そのため、コンパイル中に悪意のあるコードを実行する方法を誰かが見つけた可能性があります。

コメントで提案されているように、おかしなことがマシンで行われていないことを確認したい場合は、仮想マシンを使用してください。

34
BЈовић

私はビジネスのどこかに、特定の言語とコンパイラのバージョンのためにすでにそのようなハックを作成した賢い人がいると確信しています。このようなものを探すのに私のお気に入りの場所は、おそらく International Obfuscated Cコンテスト -(Javaに匹敵するものがあるかどうかはわかりません)でしょう。ただし、実際には、次のように想定して、リスクをどのくらい高く評価しますか。

  • 申請者があなたの会社で本当に仕事を望んでいるとあなたにもっともらしい印象を与える(訴訟ではない)

  • 男はあなたのレビューがどれだけ行われているか知らない

  • 彼/彼女はあなたが使用している正確なコンパイラのバージョンを知りません

  • 安全のために、仮想環境とオンラインコンパイラのどちらを使用しているかはわかりません

  • 効果的にレビューするには大きすぎるプログラムは受け入れない

  • 疑わしいと思われるものはコンパイルしない

  • そのようなタスクを技術的に達成する方法を実際に知っている人は世界中にあまりありません(そして、自分で既に見つけたので、グーグルするだけでは「クイックリファレンス」やチュートリアルを提供できません)。

したがって、コンパイルは理論的には「完全に安全」ではありませんが、IMHOは実際には「コンパイラが作成される」リスクが非常に低いです。

23
Doc Brown

いくつかのケースを区別する必要があります。

  1. コンパイラのバグ。すべての複雑なプログラムと同様に、コンパイラにはバグがあり、それらのバグの1つが悪用される可能性があります。
  2. トロイの木馬。攻撃者は、コンパイルプロセスの一部として、任意のコードを実行させる可能性があります。 Makefilebuild.xmlconfigureシェルスクリプトなど。技術的には、これは攻撃者のコードをコンパイルするためではなく、コンパイル環境をセットアップするためです。
  3. コンパイル時に任意のコードを実行できる言語。 Scalaのマクロ言語はScala、Common LISPのマクロ言語はCommon LISP、テンプレートHaskellのマクロ言語はHaskellです。 Scalaにはコンパイラプラグインもあり、これも任意ですScalaコンパイル時に実行されるコード。F#にはタイププロバイダがあります。
  4. コンパイル時にチューリング計算を可能にする言語。 ScalaとHaskellの型システムは、C++のテンプレートと同様に、チューリング完全です。無限ループなど、コンパイル時に任意のチューリング計算をコンパイラーに実行させることができます。 Turing-completeは、すべてのTuring計算可能関数を計算できることを意味するだけであり、ファイルシステムなどにアクセスできることを意味するわけではないことに注意してください。ただし、コンパイルに無限に時間がかかるプログラムを作成できます。
  5. 非常に長いコンパイル時間。たとえば、C#の過負荷解決のルールは非常に複雑なので、3-SAT問題をC#過負荷解決としてエンコードできます。もちろん、3-SATは有名なNPコンプリートです。つまり、現在の知識によれば、C#でオーバーロードを解決するための効率的なアルゴリズムを見つけることは不可能です。コンパイルを無限に長くすることはできませんが、コンパイルを宇宙の寿命よりも長くするのに大きなプログラムは必要ありません。これは実際には同じことです。

#4。と#5。せいぜいサービス拒否を引き起こします。実際には、C++とScalaコンパイラは、実行できる再帰の量を制限するため、実際には無限ループを作成することはできません。Scalaでは、これは単なる実装の制約ですが、C++では仕様で明示的に許可されています。

#2。質問はコードを実行しないでコンパイルすることに関するものだったため、技術的には質問の範囲外です(OTOH、深い哲学的質問があります:Haskellプログラムの型チェックが任意のチューリング計算を実行できる場合、そのコンパイルまたはプログラムの実行ですか?)

#1。ありそうもない。一方、本番コンパイラは非常に複雑であるため、バグの可能性が高くなります。一方、これらは厳密にテストされています。結局のところ、不正な形式の入力を適切に処理することは、コンパイラーのジョブ記述の一部です。それらがテストされていなくても、とにかく不正なコードで攻撃されます。コンパイラーにジャンクが投げる例については、StackOverflowの質問をご覧ください。

これにより、3が残ります。一部のコンパイラーは、コンパイル時コードがシステムに与えるアクセスの種類を制限する場合がありますが、一部のユースケースでは、完全なアクセスが不可避です。たとえば、F#の型プロバイダーの目的は、型システムがF#と一致しないデータの合成型を "偽造"することです。これにより、たとえば、厳密に型指定されたWSDLスキーマを持つWebサービスと対話できます。ファッション。ただし、これを行うには、タイププロバイダーがファイルシステムまたはWeb上のWSDLスキーマリソースにアクセスできる必要があるため、ファイルシステムとネットワークにアクセスできる必要があります。

安全ですか?技術的には違います。危険ですか?あんまり。

13
Jörg W Mittag

コンパイルコードだけではリスクはありません。 理論では、巧妙なハッカーが利用できるコンパイラにバグがある可能性がありますが、その可能性は極めて低いようです。

buildingは安全でない可能性があることに注意してください。たとえばC#の「ビルドイベント」では、ビルドの前後に実行する任意のコマンドラインを指定できます。これは明らかに危険であり、コンパイラコードでバッファオーバーフローを実行するよりもはるかに簡単に悪用できます。

3
JacquesB

推測するのではなく、答える前に実際にこのトピックについていくつかの調査を行い、( CVE Details )と考えられる最も信頼できるリソースに行きました。この公開されているセキュリティエクスプロイトの包括的なリストは、おそらく、さまざまな種類のソフトウェアの脅威レベルを評価するために実行できる最善のものです。

もちろん、利用可能な資料のallを読むのに時間はかかりませんでしたが、サンプルを作成するためにいくつかの「プライマリ」コンパイラ、IDE、およびテキストエディタを選択しました脅威の評価。ソフトウェアの実行に真剣に取り組んでいる場合は、少なくともそこにどんな脅威があるかを確認する必要があります。また、古いソフトウェアは一般に新しいソフトウェアよりもバグが多いため、実行しているもののうち最新のものを実行するのが理想的です。

まず、さまざまなテキストエディタを見てみましょう。最高のエディターが最もシンプルなようです。 Linuxシェルを使用している場合はVi、Windowsを使用している場合はメモ帳。 1つの文字が現在のエンコードスキームの外にある場合は、フォーマット機能、解析なし、データの単純な表示と解析の自動終了のないもの。 Notepad ++にもいくつかの脆弱性があります。信頼できないファイルを表示するときは、複雑なものは避けてください。

次に、IDEを確認できます。 IDEでファイルを開く場合は、一部のIDEでバグが報告されていることに注意してください。どうやらVisual Studioはエクステンションメカニズムを通じて利用可能なエクスプロイトを持っているため、ソリューションを開くのは問題があるかもしれません。 IDEを回避することで、あなたと信頼できないコードとの間の問題全体を回避できます。 VIを使用する方がはるかに安全です。

第三に、実際のコンパイラを見ることができます。 Adobe、Microsoft、Java、GNUのC/C++を含むいくつかを閲覧したところ、一般的に言えば、コンパイルコード(そしてbuilding、カスタムのmake-fileがないと仮定して)は比較的安全ですが、これらのコンパイラーのそれぞれは、実際にコンパイルされたバイナリーを実行することから発生する可能性のあるセキュリティの悪用を行います。つまり、単にコンパイルするだけではシステムを引き継ぐことができませんでしたが、コードを実行することでシステムを引き継ぐことができました。

したがって、結論として、配信方法でシステムがまだハイジャックされていない(たとえば、メールクライアントがハッキングされた、またはシステムに侵入したUSBドライブが感染したなど)と想定すると、ソースコードを読み取ってソースコードをコンパイルするとおそらく安全です。特定のソフトウェアを調査することで、たとえば、ファイルが正しいコードページにあることを検証するなどして、さらに安全にすることができます。コードの実行は、単に気にしないハードウェアでのみ行う必要があります。 VMではなく、物理的に異なるコンピュータ全体であり、ネットワークアクセスも機密ファイルや外部デバイスもありません。コードを理解していると思う場合でも、簡単な調査によると、コンパイラにもバグがあり、隠れたバッファオーバーフローエクスプロイトが背後から侵入して任意のコードを実行できる可能性がありますが、 runまたはdebugプログラムを選択します。 実際のコンパイルは安全でなければなりません。

3
phyrfox

まあ、私は「コードのレビュー」から始めます。実際にコードを実行する必要があるのはなぜですか?

それとは別に、コードを入力してコンパイルまたは実行、あるいはその両方を実行できる多くのオンラインコンパイラがあります。あなたはそれを要件にすることができます:それはこれとそのオンラインコンパイラでコンパイルされます。

オンラインコンパイラを使用したページの例を次に示します。 Online compilers

就職の面接のレビュー用のコードは、何が起こっているのか理解できないほど大きくてはいけません。

2
Pieter B

コンパイラーは通常、いくつかの巧妙なコードをコンパイルするときにユーザーのマシンをpwnしないように検証されていますか?

一般に、それらは複雑すぎて、この特性を証明することが実用的でない言語を使用して記述されることがよくあります。

おそらくこの特定の目的ではないかもしれませんが、ファズテストコンパイラの概念は少なくとも知られています( LLVMは今ではファズテスト自体を行うことができます )。コンパイラーのバグが原因でコンパイラーをクラッシュさせる入力を検出することを意図したテストは、悪用可能な欠陥も傾向にしてしまいます。

当然、興味のある特定のコンパイラが潜在的なクラッシュを見つけるためにテストされているのかファズテストされているのか、そして見つかったバグが実際に修正されているのかを調べる必要があります。経験則として、捕捉できないメモリ不足例外よりも悪いクラッシュが発生した場合、詳細をさらに調査することなく、それらが悪用に利用される可能性があるという深刻な可能性を考慮する必要があります。

見知らぬ人からのコードをコンパイルするのはどのくらい安全ですか?

残念ながら、文字列の長さはどれくらいですか。 原則としてコンパイラに到達する前に、メールがメールクライアントを利用したり、ソースコードがテキストエディタやcppcheckを利用したりする可能性があります。オンラインコンパイラを使用するというセバスチャンのコメントの提案はかなり良いものですが、もちろんコードはコンパイラが受け入れる形式でなければなりません。

もちろん、一般的なコードをコンパイル時に実行する機能を備えた言語やコンパイラーは、非常に疑わしいものです。 C++テンプレートは機能的には完全ですが、システムへの(意図された)アクセス権がないため、比較的リスクが低くなります。 BЈовићはmakeを非常にリスクが高いと述べています(見知らぬ人のコードを実行しているため、コードはたまたまC _ ++ではなくmake言語で書かれているだけです)。コンパイラーがsystemを実行する場合、同じボートにいます。私は、アセンブラーを使用していて、正しく覚えていれば、任意のコンパイル時コード実行を実行できました。これはルックアップテーブルの計算を目的としたものですが、システムコールの作成を妨げるものはないと思います。

実際には、コードが私に問題なく見え、私がそれを理解していると思う場合、コンパイルすることは非常に低いリスクであり、はるかに低いと思います「ロックダウンされたブラウザでインターネットを閲覧する」と言うよりも危険です。私は自分の汎用マシンで日常的にリスクの高いことをしていますが、それらの多くは実行しません。ウイルスラボ内または重要なサーバー上。コードがおかしそうに見える、または明らかに難読化されている場合は、コードをコンパイルするリスクはないかもしれません。なぜなら、コードが読み取り不可能なゴミに隠されたエクスプロイトを含む可能性があるだけでなく、ゴミのコードだからです。アンダーハンドコードは困難ですが、可能です。コンパイラのエクスプロイトを介してマシンを作成するアンダーハンドコードには、重要な実行可能ペイロードを含める必要があるため、極端に困難です。

これについて詳しく調べたい場合は、オンラインコンパイラをホストしている人に聞いてみてください。それが行われていない場合(NSAまたは同等のものに注意を向けない限り))、それが行われないと合理的に想定できます。彼らは、適切なサンドボックスでコンパイラーを実行します。これは、意図したよりも多くの労力がかかる可能性がありますが、少なくともサンドボックスがどれだけの頻度で問題を回避できるかを教えてくれる可能性があります。

2
Steve Jessop

これは一般的に問題ですが、設定が原因で問題は存在しないと思います。

申請者からソースコードが送られてきました。どのように、またはなぜそれが起こりましたか?

まあ明らかに3つの可能性しかない:

  1. 申請者に、特定の(明確に定義された)問題を解決して彼のスキルを評価する割り当てを与えました。
  2. 申請者は、彼が書いたクールなものを自慢したい。
  3. 申請者はジャーク、スパイ、またはその他の悪意のある人物であり、実際に採用されることに興味はありません。彼が望んでいるのは、あなたが彼のコードを実行するのに十分愚かであることです。

2)と3)について

主なリスクは2)と3)を区別することです。彼が書いたものが見る価値があるである場合、それはあなたがオンラインのソースコードを(「ニュートラル」なソースから)得ることができるものであり、あなたもすでに精通しているかもしれません。またはそれはあなたが競争相手(以前の雇用主)の知的財産を侵害するため、あなたが見るもの実際にはしたくない見てください。後者はとにかくその人を雇いたくないことを意味します。
ソースをオンラインで入手できる場合は、入手してください。著名なソフトウェア(プロプライエタリソフトウェアを含む)への申請者の貢献をクレジットのどこかで名前で確認できる場合は、そうします。
それ以外の場合は、彼があなたに送ったものはすべて無視してください。見る価値がないか、違法であるか、リスクが高い。

1)について

あなたが彼に割り当てを与えたので、申請者はあなたに何かを送りました。 any能力(私はあなたがそうしていると思います!)を持っている場合、典型的なプログラミングの割り当て(...自分で選択したことさえある!)の場合、それがもっともらしい解決策であるかどうかを知ることができます。これは、ソースコードを30秒未満(おそらく10秒)見ただけで機能するように見えます。

プログラムがおそらく30秒以内に機能する(またはプログラムが何をしているのか)と判断できない場合、それを書いたのは採用したい人ではありません。他の人間が理解して維持できるコードを書いてくれる人が欲しい。賢くなろうとしている人や、難読化されたCコンテストに定期的に勝つ人は必要ありません。プログラムが機能するかどうかは問題ではありません。他の人がコードを理解できないとすぐに、コードは「機能しません」。
プログラムはおそらく動作すると思われますが、「奇妙」に見えるものを見つけます(たとえば、Java unicodeエスケープシーケンス、C++の未加工文字列リテラル、次のようになります)トリグラフなど)、割り当てを「不合格」として扱い、次の申請者に進みます。すべてのプログラムの99%にそのようなものを含める必要はありません(そして、確かに、割り当てには含まれていません-期待する必要があります) 。したがって、そのような「奇妙な」何かを見つけた場合、申請者は採用したい人物ではありません。

コードが最初のトリアージに合格した場合は、さらに2〜3分かけてより完全に調査することをお勧めします。その後の表示に満足できる場合は、静的アナライザーを介して実行し、仮想マシンで高警告レベルでコンパイルできます。

これにより、ソースの読み取り中に見逃した可能性のある問題(未定義の動作の呼び出しや変換の絞り込みなど)が表示されます。
コンパイルでは、まず第一に、申請者に必要な勤勉さと細部への注意力があるかどうか、プログラミングのスキルがあるかどうかはそれほどではありません。アプリケーションに雇用主の名前を正しく記述し、提出前にCVをスペルチェックするのと同じように、提出するすべてのソースコードがエラーなしで(できれば警告なしで)コンパイルされることを確認することがベストプラクティスです。誰かがそれを怠った場合、あなたは彼を雇いたくないでしょう。

この時点で悪事が発生するリスク(コンパイラーを悪用するおよび VMから抜け出す)はごくわずかであり、コードに対して妥当性チェックをどのように実行したかを確認できます。起こりません。

1
Damon

ソースコードを読む:完全に安全です。ソースコードのコンパイル:完全に安全です。コンパイルされたバイナリの実行:ええと...それは状況によります。

コンパイルとは、コンピューターがソースコードを読み取って、それに相当するものをバイナリ形式で書き込むことです。コンパイル後、人間が読める形式とコンピュータが読める形式の2つのドキュメントができます。コンピュータに2番目のドキュメントを読み取らせる(実行する)まで、何も起こりません。

0
gbjbaanb

可能性が心配な場合は、古いマシン(ほとんどの人が座っているわけではありませんか?)、現在のバージョンのLinuxとコンパイラー&cをインストールし、ソースコードをコピーして、ネットワークケーブルを取り外します(またはWiFiをオフにします) )、コンパイルを行います。何か厄介なことが起こっても、それは他に影響を与えません*。

また、Makefile内のマルウェアの場合は、-nフラグ(IIRC、RTMF)を指定して実行し、実際に実行しなくても何が行われるかを確認します。

*もちろん、プログラマがマルウェアをコード化して再接続を待機する場合を除きますが、その場合は、a)マシンをワイプします。そしてb)男の履歴書をNSAに転送します、なぜなら彼は商業の世界で無駄になっているからです:-)

0
jamesqf

肝心なことは、isリスクがあるということです。他の回答が示すように、リスクはかなり小さいですが、リスクがあります。つまり、次の2つの質問をする必要があります。

  1. リスクを軽減するにはどうすればよいですか?
  2. リスクは私が気にするほど高いですか?

2番目は、この質問でここに示したものですが、この特定のケースでは間違った焦点です。リスクを軽減するための答えは明確で、すぐに利用できます:マシンでコードをコンパイルしないでください。マシンを使用せずにコンパイルする方法は2つあります。

  1. 仮想マシンを使用します(@FlorianMargaineがコメントですぐに指摘したように)。コンパイルする前にスナップショットを作成し、完了したらスナップショットを復元します。
  2. ホストされたサービス(オンラインコンパイラなど)を使用します。

リスクを軽減するこれらの方法は非常に明白で安価で簡単にアクセスできるため、リスクの大きさを分析するために多くの時間を費やす価値はありません。それらの1つを実行し、それで完了します。

0
jpmc26

Visual Studioは、信頼できない場所(ダウンロードされた場所やネットワーク共有など)からプロジェクトを開くと、実際に警告を表示します。

これが悪用される可能性のある例の1つは、WPFプロジェクトです。XAMLから.NETクラスを参照し、IntelliSenseを提供して、設計時に参照されたクラスをVSに読み込んで実行できます。

つまり、攻撃者は悪意のある.dllをbinディレクトリにドロップし、ソースコードを無害な.dllに置き換え、設計時にDLLが実行されます。最初のビルド後、すべての悪意のあるバイナリの痕跡はなくなりました。

したがって、提供されたコードはすべて「クリーン」であるにもかかわらず、コンパイラーにはバグがなく、提供された.EXEを手動で実行することはありません。悪意のあるコードがバックグラウンドで実行される可能性があります。 (その特定の攻撃から保護するために、ソリューションを開く前にディレクトリツリーにバイナリが存在しないことを確認できます。VSは、設計時にIntelliSenseを提供する前に、ソリューションをビルドするように求めます。)

同様のベクターが他の言語やOSでも存在する可能性があります。

0
Lukas Rieger