21

私は、テスト駆動開発(TDD)という最新のトレンドについて理解を深めてきました。私が行う開発のほとんどはCまたはC++です。一般的なTDDプラクティスと一般的な安全なコーディングプラクティスの間には非常に明白な矛盾があることに気づきました。本質的に、TDDは、失敗したテストがないもののために新しいコードを書くべきではないとあなたに言います。私にとって、それは、コードが安全かどうかを確認するための単体テストがない限り、安全なコードを書くべきではないことを意味します。

それは2つの問題を引き起こします:

  1. バッファオーバーフロー、スタックオーバーラン、ヒープオーバーラン、配列インデックスエラー、フォーマット文字列のバグ、ANSIとUnicodeとMBCSの文字列サイズの不一致、安全な文字列処理(HowardとLeBlancの「WritingSecureCode」から)をテストするユニットテストを効果的に作成するにはどうすればよいですか。 )?

  2. セキュリティの多くは機能しないため、標準のTDDプラクティスのどの時点でこれらのテストを含める必要があります。

驚いたことに、TDDとセキュリティについて議論している研究はほとんど見つかりませんでした。私が出くわすもののほとんどは、TDDが「コードをより安全にする」と非常に高いレベルで言及しているTDDの論文です。

上記の問題に対する直接的な答え、これに関連する調査(私はすでに調べたがあまり見つかりませんでした)、またはTDDの第一人者が住んでいる場所を探しているので、彼らのドアを(事実上)ノックすることができます。彼らが良い答えを持っているかどうかを確認してください。

ありがとう!

編集:

ファジングのトピックが出てきましたが、これはこの問題への優れたアプローチだと思います(一般的に)。これは疑問を投げかけます:ファジングはTDDに適合しますか?TDDプロセスのどこにファジングが適合しますか?

パラメータ化された単体テスト(おそらく自動化されたもの)も私の頭をよぎりました。これは、テストプロセスの早い段階でファジングのような結果を得る方法かもしれません。それがTDDのどこに当てはまるのか正確にはわかりません。

編集2:

これまでの回答ありがとうございました。この時点で、パラメーター化されたテストを活用して関数の疑似ファザーとして機能させる方法に非常に興味があります。しかし、セキュリティをテストするためにどのテストを作成するかをどのように決定するのでしょうか。そして、どうすれば攻撃スペースを適切にカバーできるかを確認できますか?

ソフトウェアセキュリティでよく知られている問題は、5つの攻撃シナリオから保護すると、攻撃者は6番目の攻撃を探して使用するだけです。それは非常に難しい猫とネズミのゲームです。TDDはこれに対して何か利点がありますか?

4

5 に答える 5

10

はい、TDD は安全なコーディングを保証するのに役立つツール/手法です。

しかし、この業界のすべてのことと同様に、それが特効薬だと仮定すると、自分の足を撃ちます。

未知の脅威

編集 2 で示したように、「5 つの攻撃シナリオから保護すると、攻撃者は 6 番目の攻撃を探して使用するだけです」。TDD は未知の脅威からあなたを守りません。その性質上、最初にテストを作成するには、何をテストしたいかを知る必要があります。

したがって、脅威番号 6 が発見されたとします (侵害によるものではなく、潜在的な攻撃ベクトルを見つけようとする別のツール/手法による内部的なものであることを願っています)。

TDD は次のように役立ちます。

  • 脅威を検証するためのテストを作成できます。
  • ソリューションを実装して脅威をブロックし、すぐに動作を確認できます。
  • さらに重要なことは、他のすべてのテストにまだ合格していれば、次のことをすぐに確認できることです。
    • 他のすべてのセキュリティ対策は引き続き正しく動作します。
    • 他のすべての機能は引き続き正しく動作します。
  • 基本的に、TDD は、脅威が発見されてからソリューションが利用可能になるまでの所要時間を短縮するのに役立ちます。
  • TDD は、新しいバージョンが正しく動作するという高い信頼性も提供します。

テスト可能なコード

TDD はテスト方法論と誤解されることが多いと読んだことがありますが、実際には設計方法論に近いものです。TDD はコードの設計を改善し、よりテストしやすくします。

専門的なテスト

テスト ケースの重要な機能は、副作用なしで実行できることです。つまり、テストを任意の順序で何度でも実行でき、失敗することはありません。その結果、純粋にテスト容易性の結果として、システムの他の多くの側面のテストが容易になります。例: パフォーマンス、メモリ使用率。

このテストは通常​​、スイート自体に直接影響を与えることなく、テスト スイート全体の特別なチェックを実行することによって実装されます。

同様のセキュリティ テスト モジュールは、テスト スイートをオーバーレイし、メモリに残っている安全なデータ、バッファ オーバーラン、既知になった新しい攻撃ベクトルなど、既知のセキュリティ上の問題を探すことができます。このようなオーバーレイは、システムのすべての既知の機能についてチェックされているため、ある程度の信頼性があります。

改良されたデザイン

TDD の副作用として生じる重要な設計改善の 1 つは、明示的な依存関係です。多くのシステムは、暗黙的または派生的な依存関係の重みに悩まされています。そして、これらはテストを実質的に不可能にします。その結果、TDD 設計は適切な場所でよりモジュール化される傾向があります。セキュリティの観点から、これにより次のようなことが可能になります。

  • 実際にネットワーク経由でデータを送信することなく、ネットワーク データを受信するコンポーネントをテストします。
  • 攻撃シナリオで発生する可能性のある、予期しない/「非現実的な」方法で動作するオブジェクトを簡単にモックアウトできます。
  • コンポーネントを分離してテストします。
  • または、生産コンポーネントの任意の組み合わせで。

単体テスト

注意すべきことの 1 つは、TDD は高度にローカライズされた (単体テスト) ことを好むということです。その結果、次のことを簡単にテストできます。

  • SecureZeroMemory()RAMからパスワードを正しく消去します。
  • または、GetSafeSQLParam()SQL インジェクションを正しく防ぐことができます。

ただし、すべての開発者が必要なすべての場所で正しい方法を使用したことを確認することは、より困難になります。
新しい SQL 関連機能を検証するテストでは、その機能が機能することが確認されます。これは、GetSQLParam の「安全な」バージョンと「安全でない」バージョンの両方で同様に機能します。

このため、「安全なコーディングを保証する」ために使用できる他のツール/手法を無視してはなりません。

  • コーディング標準
  • コードレビュー
  • テスト
于 2011-03-27T16:49:41.150 に答える
5

最初に 2 番目の質問にお答えします。はい、TDD 作品は非機能要件で使用できます。実際、そのように使われることが多いです。改善されたモジュラー設計の最も一般的な利点は機能的ではありませんが、TDD を実践するすべての人に見られます。TDD を使用して検証したその他の例: クロスプラットフォーム、クロスデータベース、およびパフォーマンス。

すべてのテストで、コードを再構築してテストできるようにする必要がある場合があります。これは TDD の最大の効果の 1 つで、コードの構造が大きく変わります。最初はこれが設計を混乱させているように見えますが、テスト可能な設計の方が優れていることにすぐに気付きます。ともかく...

文字列解釈のバグ (Unicode と ANSI) は、TDD でテストすると特に便利です。通常、悪い入力と良い入力を列挙し、それらの解釈について主張するのは簡単です。「テスト可能にする」ために、コードを少し再構築する必要があることに気付くかもしれません。これは、文字列固有のコードを分離するメソッドを抽出することを意味します。

バッファ オーバーランの場合、与えられたデータが多すぎる場合にルーチンが適切に応答することを確認することも、非常に簡単にテストできます。テストを書いて、あまりにも多くのデータを送信するだけです。彼らがあなたが期待したことをしたと断言します。ただし、一部のバッファ オーバーフローとスタック オーバーフローは、少しトリッキーです。これらを発生させることができる必要がありますが、それらが発生したかどうかを検出する方法も理解する必要があります。これは、余分なバイトを含むバッファーを割り当て、それらのバイトがテスト中に変更されないことを確認するのと同じくらい簡単かもしれません...または、他の創造的な手法かもしれません。

ただし、簡単な答えがあるかどうかはわかりません。テストには創造性、規律、およびコミットメントが必要ですが、通常はそれだけの価値があります。

  • テストする必要がある動作を分離する
  • 問題を検出できることを確認してください
  • エラーの場合に何をしたいのかを知っている
  • テストを書き、それが失敗することを確認する

お役に立てれば

于 2011-03-21T05:45:05.587 に答える
4

TDD は、安全なシステムを構築するための最良の方法です。Microsoft が開発したすべてのソフトウェアはファジングされており、これが脆弱性が劇的に減少した最大の理由であると言えます。この目的には、 Peach フレームワークを使用することを強くお勧めします。私は個人的に Peach を使用して、バッファ オーバーフローを見つけることに大きな成功を収めました。

ピーチ ピット ファイルは、アプリケーションで使用されるデータを記述する方法を提供します。テストするインターフェイスを選択できます。アプリケーションはファイルを読み取りますか? 開いているポートはありますか?入力がどのように見えるか、およびアプリケーションとの通信方法を peach に伝えた後、それを緩めることができます。私は、アプリケーションが自分自身を吐き出すための厄介な入力をすべて知っています。

すべてを実行するために、peach には素晴らしいtesting harness機能があります。アプリケーションがクラッシュした場合、peach にはデバッガーが付属しているため、それがわかります。アプリケーションがクラッシュすると、peach はアプリケーションを再起動してテストを続けます。Peach はすべてのクラッシュを分類し、コア ダンプをアプリケーションのクラッシュに使用した入力と照合できます。

于 2011-03-21T06:54:20.613 に答える
0

パラメータ化されたテスト

私の仕事ではバッファ オーバーラン テストを行っていませんが、テンプレート テストの概念はあります。これらのテストは、テストするケースの特定のデータを要求するようにパラメーター化されています。次に、メタプログラミングを使用して、各ケースのパラメーターをテンプレートに適用することにより、実際のテストを動的に作成します。これには決定論的であるという利点があり、自動化されたテスト スイートの一部として実行されます。

私のTDDの実践

私の仕事では、受け入れテスト駆動開発を行っています。私たちのテストのほとんどは、たまたまフルスタックの機能テストに近いものです。その理由は、ユーザー主導のアクションの動作をテストして保証する方が価値があることがわかったからです。パラメータ化されたテストからの動的テスト生成などの手法を使用して、最小限の作業でより多くのカバレッジを提供します。これは、ASCII と UTF8、API 規則、およびよく知られたバリアント テストに対して行います。

于 2011-03-21T21:17:34.277 に答える