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


120

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

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

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

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


56
確実に知る唯一の方法は、知人が雇用主に理由を尋ねる場合です。しかし、推測するリスクがあります。静的型チェックは、ミッションクリティカルなソフトウェアの正確性を支援する別のレイヤーです。もちろん、バグを取り除くことはできませんが、正しい方向への一歩です。コンピューターが作業の一部を行っています。(はい、私はこれが神聖な戦争の領土であることを知っています)。
アンドレスF.


75
PHP + JavaScriptで記述されたミサイル制御ソフトウェアは必要ありません。
Tulainsコルドバ

16
HRデータは「低セキュリティレベル」ではありません。会社が私の雇用と個人データをできる限り安全に保つことを期待しています。
gbjbaanb

5
@gbjbaanb OPの意味するところは、ここで最悪のシナリオではないことです。
アンドレスF.

回答:


126

特定のコードの機能について、他のプログラマーや監査員にはすぐには分からないコードの一部に隠れてしまう動的言語でできる「ニート」なことがたくさんあります。

irb(対話型ルビーシェル)の次のシーケンスを考えます。

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クラスを開いてfooreturn メソッドを定義し、"foobar!"呼び出しました。これはうまくいきました。

これはオープンクラスとして知られており、セキュリティや整合性を備えたルビーでコードを記述するたびに悪夢に見舞われます。確かにそれはあなたに非常にすてきなことを非常に速くさせることができます...しかし、誰かが文字列を保存するたびに、それをファイルに保存するか、ネットワークを介して送信するようにできました。そして、この少しの文字列の再定義は、コードのどこにでも入れることができます。

他の多くの動的言語には、同様のことができるものがあります。PerlにはTie :: Scalarがあり、背後で特定のスカラーの動作を変更できます(これはもう少しわかりやすく、特定のコマンドが必要ですが、他の場所から渡されるスカラーが問題になる可能性があります)。Perl Cookbookにアクセスできる場合は、Recipe 13.15-tieを使用したマジック変数の作成を参照してください。

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


これは、クロージャーが定義された環境にアクセスする機能により、Rubyでさらに興味深いものになります(YouTube:RubyをRubyConf 2011からRubyをリーズナブルに保つことをJoshua Ballancoが参照)。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 
バー
> :)
クックス
バー
b.rb:20:in `qux ':MWHWAHAW!(ランタイムエラー)
    b.rb:30:から `'
〜/ $ ruby​​ foo.rb 
バー
> :)
クックス
b.rb:20:in `bar ':MWHWAHAW!(ランタイムエラー)
    b.rb:29:in `'から

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

このコンテキストでアクセスできる変数、メソッド、selfの値、および場合によっては反復子ブロックはすべて保持されます。

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

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

これは、静的解析を不可能にする上記のオープンクラスよりも優れています。上記で示されているのは、他の場所に渡されるクロージャーは、それが定義された完全な環境を運んでいるということです。これは、ファーストクラス環境として知られています。これは、その時点で利用可能な環境とすべてのバインディングです)。クロージャのスコープで定義された変数を再定義できます

良いか悪いか、ルビーについて不満を言うか(メソッドの環境にアクセスできるようにしたい用途があります(PerlのSafeを参照))、「政府プロジェクトでルビーを制限する理由」の質問上記のリンク先の動画で実際に回答があります。

とすれば:

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

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

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

しかし、時間が経つにつれて、最初に考えていたよりも、ファーストクラスの環境の方が困難であり、パワーが少ないことに気付きました。この時点で、最高クラスの環境はせいぜい役に立たず、最悪の場合危険であると信じています。

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


3
私はこの点を理解していません。あなたはスカラーの振る舞いを変えることを可能にするPerlクラスについて言及します。ただし、Perlは安全な環境を含め、広く使用されています。言語にこれらの機能があるだけでは、その言語を使用できないということにはなりません。Rubyの特定のケースでは、ターゲット環境がRubyをサポートしていない可能性があります。個人的には、Rubyがどのシステムでも使用できることは一度も見たことがないし、Rubyが承認されたソフトウェアリストに載っているかどうかすらわからない。
トーマスオーエンズ

17
@ThomasOwens-この答えの私の理解は、キーが"many approaches to static analysis of security in code doesn't work"であるため、分析できないため(少なくともこのグループでは)キーは拒否されます。私がそれを正しく解釈しているのか、それがそれを拒否する正当な理由であるのか、私にはわかりません。
ボブソン

21
承認済みのソフトウェアリストに関する情報が不足しているため、動的言語の問題についてのみ推測できます。ただし、金融ソフトウェアで同様の問題が発生し、セキュリティ問題のために言語で静的分析を実行できないため、支払いカード業界のチェックが失敗しました。言語の性質により静的分析を覆すことができる動的言語で2つの例を示しました。またこれが理論的にも正確ではない理由を指摘しました。一部の場所ではperlが許可されており、他の場所では許可されていない可能性があります。理由については推測しかできません。

2
他の多くの言語(Obj-C、C、C ++など)でも標準ライブラリ関数を再定義できます。
マーティンウィックマン

12
さて、.NET拡張メソッドは上記のRubyと同じではありません。静的クラスを簡単に入力する方法を作成します。実際には、メソッドをクラスに追加するわけではありません。
グラハム

50

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

通常、セキュリティ分析ツールは、動的な振る舞いに苦労します。

例えば:

任意の実行の.NETなどの現代的な機能と書かれたプロジェクトASP.NET MVCEntity Frameworkのようなものを通じてのVeraCodeをし、レポートに受信偽陽性の洗濯物のリストの種類を参照してください。

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

そのようなツールに強く依存しているエンティティを扱っている場合、技術的な専門知識とリソースがない場合、プロジェクトを手動で評価し、プロジェクトが適切に書かれているかどうかを確認するために、安全でないものを考慮する必要があります安全。

一般にコンピューターシステムが危険なものやひどく高価なものを制御しない民間の操作では、軽減策は偽陽性について話し合うことです。

銀行業務では、依然として誤検知を緩和する可能性がありますが、各項目の詳細について議論するのにもっと多くの時間を費やすことになります。これは急速に法外なコストになり、より伝統的な方法を使用し始めます。

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

組織は一般に、知っている最悪の場合にセキュリティポリシーを作成するため、些細なことを書いている場合でも、重要なシステムを備えた組織にそれを書いている場合、デフォルトでは一般的にそれを保持します誰かが特定の例外を要求しない限り、より高い基準。


4
そして、それは単なる誤検知です。本当に心配なのは、偽陰性の可能性です。
スティーブンC

3
正直なところ、これらのツールでの私の経験は一般的にひどいものでした。おそらく、実際に議論する価値のある何かを見つけるのに、1/200から1/1000の割合で何かを。また、コードベースまたはフレームワークの数千のスポットで使用されていることがわかっている誤検知を取得したとき、それがほんの数回しか特定されていないため、正確には自信がありません。問題は、spec#のような正式な言語で始めない限り、これらのツールの1つを構築するときに、ネガティブ証明を効果的に実装していることです。
ビル

33

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

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


32

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

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

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

引用しすぎるのは嫌いですが、このようなプロジェクトに静的な言語(ADAなど)が使用されている理由は次のとおりです。

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

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

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


3
「Adaの安全重視のサポート機能のため、商用ロケット(Ariane 4および5など)で使用されています」、もちろん最初のAriane 5はソフトウェアのバグにより爆発したため、特効薬はありません。
アンドリューマーシャル14年

5
@AndrewMarshall:「レポートではソフトウェアのバグが直接の原因であると特定されましたが、他の調査者は原因をシステム設計の失敗や管理の問題と見なしています」-異なる言語(JavaやC ++など)で記述されたコードがロケットが軌道に乗る。
マーティンシュレーダー14年

@MartinSchröderああ、私はエイダがこのアプリケーションで他の人よりも優れている可能性が高いことを疑ってはいません。別の言語は、Adaでは不可能だった無数のバグを通過させたかもしれません。
アンドリューマーシャル14年

13

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

Is this the government being slow to adopting new technologies?

これは誤解です-動的言語は新しい技術ではなく、かなり古いものです。問題は、動的言語(たとえば、弱い/動的な型指定など)が原因で問題が発生し、その問題に多大な費用がかかった場合、同じ間違いをもう一度できないようにするポリシーを受け入れることができるということです。機密性の高いシステムでの動的言語の使用の禁止。

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

セキュリティが懸念される場合は、実際のユースケースを確認する必要があります。たとえば、Ruby on RailsのWebページはJavaのWebページよりも自動的に安全性が低いとは思いません。


2
私見より多くのバグがちょうど言って...正確には、ほとんどの動的言語が最初の場所で許可されません何かである何よりも検出されなかったバッファオーバーフローにより、「飲み込まれた」
miraculixx

@miraculixx確かに、Java / C#および同様の言語がRubyよりも多く使用されているのには理由があります。彼らは防御的です-彼らはすべてをチェックします。C / C ++では、適切なコーディング標準を使用することにより、防御力を強化できます。すべてのチェックを強制することもできます。しかし、機密性の高いアプリケーションをrubyまたはjavascriptで記述することを想像できますか?隠れたバグの可能性は大きいです。
サルタン

確かに、できます。プログラミング言語とは無関係に、ソフトウェアを徹底的にテストする必要があることにおそらく同意します。回帰を避けるために、テストはユニットテスト、BDDなどを使用して自動化するのが最適です。専門的なアプローチ(機密性の高いアプリケーションですか?)を想定して、十分なテストカバレッジを達成することは管理されたプロセスであり、偶然に任されているわけではありません。そのため、C / C ++、Javaには、隠れたバグの点で、ルビーやjavascriptのようなものよりも有利であるとは思えません。プログラマースキル?C ++ではより技術的であり、Javaでは疑わしいが、言語の問題はほとんどない。より技術的な!=製品の品質。
miraculixx

6

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つの値すべてを単一の名前付きパラメーターの単一の配列値として渡すことができる場合のように、配列にすることができます。

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

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

静的に型付けされた言語で同様のエラーを発生させる方法はありますが、ありそうにありません。優れた開発者は$i、クエリに連結する前に、可能なことを検討します。静的に型付けされた言語では$i、整数でなければならないことを強制するのは非常に簡単で、このようなセキュリティに敏感なコードでは、それは最も確実に行われます。

さらに、コードは、項目を反復処理する前に、値が配列であるかどうかを実際にチェックします。そして、この脆弱性を可能にする失敗の2番目の部分があります。連想配列と「通常の」配列の両方がtrueを返しますis_array。C#では、辞書と配列の両方がIEnumerableであることも事実ですが、辞書キーをこのような配列インデックスと意図的に、あるいは偶然に混同するコードを構築することは困難です。


2

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

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

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

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

これは、コントロールカルチャでは常に発生します。多かれ少なかれ毎日見ています。それは意味がありませんが、それはそれが行く方法です。この非常に関連性の高いトピックについて詳しくお読みになりたい場合は、シュナイダーの著書「リエンジニアリングの代替」をお勧めします。Schneiderの本に基づいたMichael Sahoto / Agilitrixの文化図は次のとおりです。 ここに画像の説明を入力してください


18
-1安全性が重要なシステムのために、言語が別の言語よりも選択される理由(リアルタイム、静的タイピング、ランタイムチェック)には多くの正当な技術的理由があります。その理由は、100%の文化、私たちと彼ら、そしてarbitrary意的なものであり、この場合、IMOはまったく間違っていることを意味します。
マイケルジャスパー

8
「言語は安全でも安全でもありません」-stackoverflow.com/a/14313277/602554を参照してください。一部の言語は他の言語よりも確実に「安全」です。
マイケルジャスパー

2
おそらくあなたの好みに合わせて私の答えを更新しました。一部の言語は特定の問題を回避するのに役立ちますが(場合によっては他の言語を導入することもあります)、システムの安全性は、使用する言語よりも記述するコードに依存することだと考えています。
マーティンウィックマン

2
@MartinWickman:a)SQL / HTMLインジェクションとバッファオーバーフローはいくつかのタイプシステムによって解決されます。エスケープされた入力とエスケープされていない入力には異なるタイプがあるため、どの方法で処理する必要があるかがわかります。b)「安全なプロジェクト」のすべてのセキュリティ問題が必ずしも妥協を意味するわけではありません。飛行機を走らせているソフトウェアが「セキュリティ」の問題ではない場合でも、バグを持ちたくありません(つまり、システムを引き継ぐために使用することはできません)。
マチェイピエチョトカ

5
-1事実の正確性の問題。バッファオーバーフローエクスプロイトは、C言語に固有の問題です。スタックに文字列バッファーを割り当てることができない言語では、これらのことを聞いたことはありません。また、Parametersの使用が単に許可されているのではなく、必要であるという仮説的なSQL方言を想像することはまったく難しくありません。この言語ではSQLインジェクションは不可能です。そのため、適切に設計された言語、いくつかの一般的な種類の攻撃からユーザーを保護できます。
メイソンウィーラー14年

2

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

DoDが開発または調達したソフトウェアの標準は、防衛情報システム局(DISA)によって公布されています。彼らのアプリケーションセキュリティ-アプリケーションセキュリティ開発セキュリティ技術実装ガイド(STIG)は、任意の特定の言語を禁止するものではありません。Rubyについては言及していませんが、同様に動的なPerlとPythonについては言及しています。さまざまなトピックのコンテキストでそれらに言及しています(確立されたコーディング標準に従って、コマンドインジェクションの脆弱性を回避するなど)。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.