web-dev-qa-db-ja.com

米国政府が安全なプロジェクトに動的言語を許可しないのはなぜですか?

現在、米軍向けのプロジェクトに取り組んでいる人がいます(低セキュリティレベル、非戦闘人材タイプのデータ)。

プロジェクトコードの初期状態が軍隊に提出され、レビューが行われ、ある種のセキュリティアナライザーツールを介してプログラムが実行されました。コードの既知のセキュリティ問題のレポートと、最終製品の納品前に実装する必要がある必要な変更が返されました。

解決する必要がある項目の1つは、動的言語であるため、 Ruby で記述されたプロジェクトの一部を削除することでした。

安全な設定で動的言語を使用できないようにする背景/理由は何ですか?これは政府が新しい技術を採用するのが遅いのですか?または、動的言語は静的言語と比較して追加のセキュリティリスクをもたらしますか(ala C++ または Java )?

122
Patrick

動的言語で実行できる多くの「きちんとした」ことがあり、特定のコードの機能に関して他のプログラマーまたは監査人にはすぐにはわからないコードの一部に隠れてしまう可能性があります。

Irb(対話型Rubyシェル)で次のシーケンスを検討してください:

irb(main):001:0> "bar".foo
NoMethodError: undefined method `foo' for "bar":String
        from (irb):1
        from /usr/bin/irb:12:in `<main>'
irb(main):002:0> class String
irb(main):003:1> def foo
irb(main):004:2> "foobar!"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> "bar".foo
=> "foobar!"

そこで起こったのは、文字列定数でメソッドfooを呼び出そうとしたことです。これは失敗しました。次に、Stringクラスを開いてメソッドfooを定義し、o "foobar!"を返し、それを呼び出しました。これはうまくいきました。

これはオープンクラスと呼ばれ、Rubyでセキュリティや整合性のあるコードを書くことを考えるたびに悪夢を覚えます。確かに、きちんとした処理をかなり高速に実行できます。しかし、誰かが文字列を保存したり、ファイルに保存したり、ネットワーク経由で送信したりするたびに作成することもできます。そして、文字列を再定義するこの少しは、コードのどこにでも隠れることができます。

他の多くの動的言語には、実行できる類似の機能があります。 Perlには Tie :: Scalar があり、特定のスカラーがどのように機能するかを舞台裏で変更できます(これは少しわかりやすく、特定のコマンドを表示する必要がありますが、他の場所から渡されるスカラーです)問題になる可能性があります)。 Perlクックブックにアクセスできる場合は、レシピ13.15-tieを使用したマジック変数の作成を参照してください。

これら(および他の場合は動的言語の一部であることが多い)のため、コード内のセキュリティの静的分析に対する多くのアプローチは機能しません。 PerlとUndecidability は、これが事実であることを示し、構文の強調表示(whatever / 25 ; # / ; die "this dies!";は、whateverが引数を取るかどうかを定義できるため、問題を提起します実行時構文ハイライターまたは静的アナライザーを完全に無効にします)。


Rubyでは、クロージャが定義された環境にアクセスできるため、これはさらに興味深いものになる可能性があります(Joshua BallancoによるRubyConf 2011の YouTube:Keeping Ruby Reasonable を参照)。私は MouseTheLuckyDogによるArs Technicaのコメント からこのビデオを知っていました。

次のコードを検討してください。

def mal(&block)
    puts ">:)"
    block.call
    t = block.binding.eval('(self.methods - Object.methods).sample')
    block.binding.eval <<-END
        def #{t.to_s}
          raise 'MWHWAHAW!'
        end
    END
end

class Foo
    def bar
        puts "bar"
    end

    def qux
        mal do
            puts "qux"
        end
    end
end

f = Foo.new
f.bar
f.qux

f.bar
f.qux

このコードは完全に表示されますが、malメソッドは別の場所にある可能性があります...もちろん、オープンクラスでは、別の場所に再定義できます。

このコードを実行する:

〜/ $ Ruby foo.rb 
 bar 
>:)
 qux 
 bar 
 b.rb :20: `qux ':MWHWAHAW! (RuntimeError)
 from b.rb:30:in `'
〜/ $ Ruby foo.rb 
 bar 
>:)
 qux 
 b.rb:20:in `bar ':MWHWAHAW! (RuntimeError)
 from b.rb:29:in `'

このコードでは、クロージャーは、そのスコープのクラスで定義されているメソッドおよびその他のバインディングのallにアクセスできました。ランダムなメソッドを選び、それを再定義して例外を発生させました。 (このオブジェクトが何にアクセスできるかについては、Rubyの Binding クラスを参照してください)

変数、メソッド、セルフの値、およびこのコンテキストでアクセスできるイテレータブロックがすべて保持されます。

変数の再定義を示す短いバージョン:

def mal(&block)
    block.call
    block.binding.eval('a = 43')
end

a = 42
puts a
mal do 
  puts 1
end
puts a

これは、実行すると次のように生成されます。

 42 
 1 
 43 

これは、静的分析を不可能にする、前述のオープンクラスを超えるものです。上に示されているのは、どこかで渡されたクロージャーが、それで定義された完全な環境を運ぶことです。これは、 ファーストクラス環境 として知られています(関数を渡すことができるときと同じように、それらはファーストクラスの関数です。これはenvironmentであり、その時点で使用可能なすべてのバインディングです)。クロージャのスコープで定義されたany variableを再定義できます。

良いか悪いか、Rubyに不満があるかどうか(メソッドの環境に到達できるようにwantを使用する場合があります(Perlの Safe を参照) ))、「なぜRubyは政府プロジェクトに制限されるのか」という質問は、上記のリンク先のビデオで実際に回答されています。

とすれば:

  1. Rubyでは、クロージャーから環境を抽出できます
  2. Rubyはクロージャーのスコープ内のすべてのバインディングをキャプチャします
  3. Rubyはすべてのバインディングをライブで変更可能として維持します
  4. Rubyには新しいバインディングがあり、古いバインディングをシャドウします(環境を複製したり、再バインディングを禁止したりするのではなく)

これらの4つの設計選択の影響により、コードのビットが何をするかを知ることは不可能です。

この詳細については、 Abstract Heresiesブログ を参照してください。特定の投稿は、そのような議論があったSchemeに関するものです。 (SOに関連: Schemeがファーストクラス環境をサポートしないのはなぜですか?

しかし、時間が経つにつれ、最初のクラスの環境では、当初考えていたよりも多くの困難があり、電力が少ないことに気付きました。この時点で、私はファーストクラスの環境はせいぜい役に立たず、最悪の場合は危険だと思います。

このセクションがファーストクラス環境の危険性の側面と、提供されたソリューションからRubyを削除するよう求められる理由を示しているといいのですが。 Rubyが動的言語であるだけでなく(他の回答で述べたように、他の動的言語は他のプロジェクトで許可されています)、特定の問題があるために、一部の動的言語について推論がさらに困難になります。

126
user40980

評価がセキュリティのみであり、単なる受け入れスキャンではない(つまり、RubyはRubyをサポートしたくないので受け入れない)と仮定すると、次のようになります。

セキュリティ分析ツールは、通常、動的な動作で悪い時間を過ごします。

例えば:

ASP.NET MVC および Entity Framework のような最新の機能で記述された 。NET プロジェクトを Veracode のようなものを介して実行しますレポートで受け取る誤検知のランドリーリストの種類を確認します。

Veracodeは、.NET 4コアライブラリ内の多くの基本的なテクニックを、「サポートされていないフレームワーク」としてサポートされていない、またはベータ版としてリストしています。

そのようなツールに強く依存しているエンティティを処理している場合、技術的な専門知識とリソースを持たない場合、それらを安全でないと見なし、手動で評価する必要がありますプロジェクトを作成し、適切に記述され、安全かどうかを確認します。

一般に、コンピューターシステムが危険なものや非常に高価なものを制御しない民間の操作では、緩和策は誤検知について話し合うことであり、それらは一般に一括で受け入れられます。

銀行業務では、依然として誤検知の軽減の可能性がありますが、各項目の特徴について話し合うために、より多くの時間を費やすことになります。これは急速にコストが非常に高くなり、従来の方法の使用を開始します。

軍事、航空、重工業などでは、システムはひどい故障モードを持つものを制御できるため、言語やコンパイラなどについて非常に厳しいルールが適用される場合があります。

組織は通常、彼らが知っている最悪の場合のためのセキュリティポリシーも記述します。そのため、些細なことを書いている場合でも、重要なシステムがある組織のために書いている場合は、デフォルト誰かが特定の例外を要求しない限り、通常はそれをより高い水準に保つことになります。

50
Bill

動的言語は、防衛および軍事アプリケーションで使用できます。私は個人的にPerlとPython= DoDアプリケーションで使用し、配信しました。PHPとJavaScriptが使用およびデプロイされていることも確認しました。私の経験では、必要な環境が承認され、さまざまな可能なターゲットシステムにインストールされているため、私が見たコンパイルされていないコードはシェルスクリプトとPerlです。

これらの言語が動的である可能性が最も高いという事実は問題ではありません。これらの言語のインタープリターは、ターゲットシステムでの使用が承認されている必要があります。インタープリターの使用が承認されていない場合(または、おそらく承認されているが、ターゲットシステムに展開されていない場合)、その言語は使用できません。安全なシステムで特定のインタープリター(または任意のアプリケーション)を使用するには、ソースの分析、ターゲット環境のソースからコンパイルする機能、バイナリーの追加分析、既存のインフラストラクチャとの競合がないことを確認するなど、セキュリティのハードルがいくつも必要です。

33
Thomas Owens

F-16のMM のコードを作成するために、国防総省(国防総省)へのインタビューに少し時間を費やしました。非開示に違反することなく:MMUは、F-16のほぼすべての機能を制御するコンピューターユニットです。ランタイムバグなどのエラーが発生しないことが(明らかに)重要です。飛行中システムがリアルタイムのコンピューティング操作を実行することも同様に重要です。

これやその他の歴史的な理由により、このシステムのすべてのコードは ADA、静的オブジェクト指向プログラミング言語 で記述またはコンパイルされています。

Adaの安全性が重要なサポート機能により、軍事用途だけでなく、ソフトウェアのバグが深刻な結果を招く可能性のある商用プロジェクトでも使用されています。航空電子工学および航空交通管制、商用ロケット(たとえば、Ariane 4および5)、衛星およびその他の宇宙システム、鉄道輸送および銀行。たとえば、ボーイング777のフライバイワイヤーシステムソフトウェアはエイダで作成されました。

引用しすぎたくありませんが、これは、このようなプロジェクトで正確に静的言語(ADAなど)が使用される理由をよく説明しています。

他の一部の言語では実行時まで検出できないバグや、明示的なチェックをソースコードに追加する必要があるバグを回避するために、多数のコンパイル時チェックがサポートされています。たとえば、構文では、エンドトークンの不一致によるエラーを防ぐために、明示的に名前を付けてブロックを閉じる必要があります。強い型付けを順守することで、コンパイル時または実行時に、多くの一般的なソフトウェアエラー(パラメーターの誤り、範囲違反、無効な参照、型の不一致など)を検出できます。並行性は言語仕様の一部であるため、コンパイラーは潜在的なデッドロックを検出できる場合があります。コンパイラーは通常、スペルミスのある識別子、パッケージの可視性、冗長な宣言などもチェックし、エラーの修正方法に関する警告と有用な提案を提供できます。

Adaは、未割り当てメモリへのアクセス、バッファオーバーフローエラー、範囲違反、オフバイワンエラー、アレイアクセスエラー、およびその他の検出可能なバグから保護するためのランタイムチェックもサポートしています。これらのチェックは、実行時の効率のために無効にすることができますが、効率的にコンパイルできることがよくあります。また、プログラムの検証に役立つ機能も含まれています。これらの理由により、Adaは重要なシステムで広く使用されており、異常が発生すると、事故による死亡、けが、深刻な経済的損失などの非常に深刻な結果につながる可能性があります。 Adaが使用されるシステムの例には、航空電子工学、鉄道、銀行、軍事および宇宙技術が含まれます。

Adaの動的メモリ管理は高レベルでタイプセーフです。 Adaには一般的な(あいまいな)「ポインタ」はありません。また、ポインタ型を暗黙的に宣言することもありません。代わりに、すべての動的メモリの割り当てと割り当て解除は、明示的に宣言されたアクセスタイプを通じて行われる必要があります。各アクセスタイプには、メモリ管理の低レベルの詳細を処理するストレージプールが関連付けられています。プログラマーは、デフォルトのストレージプールを使用するか、新しいストレージプールを定義できます(これは特に、Non-Uniform Memory Accessに関連します)。すべて同じタイプを指定し、異なるストレージプールを使用するいくつかの異なるアクセスタイプを宣言することもできます。また、この言語は、コンパイル時と実行時の両方でアクセシビリティチェックを提供します。これにより、アクセス値が指すオブジェクトのタイプよりもアクセス値が長くならないようにします。

32
Michael Jasper

DoDとNASAのどちらにも長いプログラミングの歴史があり、プログラミングが失敗すると数十億ドルもかかります。どちらの機関も、同じ間違いを繰り返さないように保護するプロセスを受け入れています。

Is this the government being slow to adopting new technologies?

これは誤解です。動的言語は新しいテクノロジーではなく、かなり古いものです。問題は、動的言語(弱い/動的型付けなど)が原因で問題が発生し、その問題に多大な費用がかかる場合、同じ間違いを繰り返さないようにするポリシーを受け入れることができるということです。機密システムでの動的言語の使用を禁止します。

動的言語は多くの場合、バグを「飲み込み」、予期しない動作が発生します。これは敏感なシステムでは非常に危険です。何か問題が発生している場合は、できるだけ早くそれを知りたいです。

セキュリティが懸念される場合は、実際の使用例を確認する必要があります。たとえば、Ruby on Rails Webページは、Javaウェブページ。

13
Sulthan

Drupalの SA-CORE-2014-005 を説明して、既存の回答に追加したいと思います。これは、SQLインジェクションと最終的に任意のコード実行を可能にする非常に重大な脆弱性です。これは、PHPの動的型付けと緩やかなランタイム型付け規則が原因です。

この問題のパッチ全体は次のとおりです。

_-      foreach ($data as $i => $value) {
+      foreach (array_values($data) as $i => $value) {
_

このコードは、SQLインジェクションを防ぐために設計されたSQL抽象化レイヤーの一部です。これは、名前付きパラメーターを持つSQLクエリと、各名前付きパラメーターの値を提供する連想配列を取ります。 WHERE x IN (val1, val2, val3)のような場合、値は配列にすることができます。この場合、3つの値はすべて、単一の名前付きパラメーターの単一の配列値として渡すことができます。

この脆弱性は、コードが_$i_の_$i => $value_が値の整数インデックスである必要があると想定しているために発生します。整数はエスケープする必要がないため、この "インデックス"をパラメーター名の一部としてSQLクエリに直接連結します。

Drupalにとって残念なことに、PHPはそのような保証を提供していません。キーが文字列である別の連想配列を渡すことが可能であり、このループは次のように文字列キーをクエリに連結します-です(コードは整数のみである可能性があるとコードが考えていることに注意してください)。

静的に型付けされた言語で同様のエラーを発生させる方法はいくつかありますが、可能性は低いです。優れた開発者は、クエリに連結する前に、_$i_の可能性を検討します。静的に型付けされた言語を使用すると、_$i_が整数でなければならないことを強制することは非常に簡単で、このようなセキュリティ上重要なコードでは、確実に実行されます。

さらに、コードは実際に、項目を反復する前に値が配列であるかどうかをチェックします。そしてここに、この脆弱性を可能にする失敗の2番目の部分があります。結合配列と「通常の」配列の両方が_is_array_に対してtrueを返します。 C#ではディクショナリと配列の両方がIEnumerableであることも事実ですが、このような配列インデックスをディクショナリキーと意図的にさえも、偶然にさえも混乱させるコードを構築することは困難です。

6
Roman Starkov

私の知る限り、国防総省の公式の方針は、一般的に動的言語を禁止していません。

国防総省によって開発または調達されたソフトウェアの標準は、 国防情報システム局 (DISA)によって公布されています。彼らの Application Security-Application Security&Development Security Technical Implementation Guide(STIG)は、特定の言語を禁止していません。 Rubyについては触れていませんが、PerlおよびPythonは同様に動的です。さまざまなトピック(確立されたコーディング標準に従って、コマンドインジェクションの脆弱性を回避するなど)のコンテキストでそれらについて述べています)について述べています。

おそらく、表示されているのは過度に厳格なスキャンツール(STIGで言及されているいくつかの異なるツールがあり、それぞれが独自のルールの解釈を持っている可能性があります)および/またはその出力の過度に厳密な解釈です。

2
nobody

コードベースが安全であるかどうかは、コードの記述方法、コードのテスト方法、開発および展開プロセスの検証と監視方法に依存します。言語は安全でも安全でもありません。それはあなたがコーディングする方法です。

悪意のある入力(SQLインジェクション、バッファオーバーフロー)、ウイルス、ルートキット、トロイの木馬によるセキュリティインシデントの大部分。それからあなたを守る言語はありません。

したがって、「安全でない」言語クラスを禁止することは正当な理由ではありません。

誰かが、何らかの理由で-知らされているかどうかにかかわらず-これらの言語を禁止することを決定したと思います。しばらくすると、組織的真実になりました。一部のプロジェクトではその時点でそれは本当だったかもしれませんが、コントロールカルチャーは決定の変更に熱心ではなく(間違っていることを認めます)、むしろ好んでいます単純なルール。彼らはルールと規制で繁栄し、それが意味があるかどうかに関係なく重要ではありません、重要なのは認識される安全です。

これは、コントロールカルチャーでは常に発生します。私はそれを多かれ少なかれ毎日見ています。それは意味がありませんが、それはそうです。この非常に関連性の高いトピックの詳細を読みたい場合は、シュナイダーの本「 The Reengineering Alternative 」をお勧めします。以下は、シュナイダーの本に基づく Michael Sahoto/Agilitrixによるカルチャー図 です。 enter image description here

2
Martin Wickman