web-dev-qa-db-ja.com

メモリを安全にするトリッキーなコード

私は、メモリの安全性について学び、安全なCコードを書く学生のための宿題の課題を設計しています。この一環として、バッファオーバーラン、配列の範囲外エラー、および/またはその他のメモリ安全性エラーのないCコードを書くことが重要な小さなプログラミングタスクを探しています。そのようなタスクの良い例は何でしょうか?

つまり、必要な機能を指定します。彼らはそれをCで実装します。また、実装時に注意を怠ると、コードにメモリセーフティの脆弱性が存在する可能性が非常に高くなります。理想的には、タスクを扱いやすいサイズに保つために、簡潔に(せいぜい数百行のコードで)実装できるものを好み、そのタスクが何らかの形で産業上または実際に関連性があり、現実的である場合は、非常にクールです。または実際のプログラミングの代表。

別のドメインの例を示すと、並べ替えられたリストにバイナリ検索を実装することは、簡単に指定できるプログラミングタスクの典型的な例であり、実装を慎重に行わないと、何らかのロジックバグが発生する可能性が非常に高くなります(たとえば、1つずれたエラー、一部の入力での無限ループなどです。セキュリティ、特にメモリセーフティの脆弱性に対応する適切なタスクはありますか?

16
D.W.

重要なバッファ処理の典型的な例は、任意の長さの文字列を含むことができるバイナリファイル(またはネットワークパケット)の解析です。 (いつかバッファオーバーフローのバグがなかったASN.1パーサーはありますか?)

たとえば、 PNGファイル内のテキストデータチャンク の形式を考えます。

キーワードとテキスト文字列は、ゼロバイト(ヌル文字)で区切られています。キーワードもテキスト文字列もnull文字を含むことはできません。テキスト文字列はnotnullで終了します(チャンクの長さが終了を定義します)。

したがって、宿題はすべてのテキストデータをPNGファイルで出力するツールになる可能性があります。

プレーンテキストでも、任意の長い行を処理する必要があり、したがってバッファのサイズを動的に変更する必要がある場合、それほど簡単ではありません。例えば:

パラメータなしで tail を実装します。 (行はどの静的バッファーよりも長くなる可能性があります。ファイル全体が使用可能なメモリーよりも大きくなる可能性があります。)

12
CL.

人々が構造体から文字データを解析する必要がある場合、特にそれが通常nullで終了するバッファであるが、ターミネータなしのバッファのサイズである場合は、多くの問題が発生します。

short canary = 0x5678;
struct customer {
    char name[4];
    char suffix[3];
};
short fencepost = 0x1234;

「Joe」や「Jr」などのデータを顧客に入力してもらいます。すべてのデータをこの正確な形式で出力するように依頼します。

canary: 0x5678
name: Joe
suffix: Jr
fencepost: 0x1234

次に、お客様に「John」と「Esq」を入力してもらいます。出力は次のようになります。

canary: 0x5678
name: John
suffix: Esq
fencepost: 0x1234

これは一般的で簡単な作業です。これは、カナリアを殺すので、バッファにstrcpy( "Esq")するだけではできないことを教えてくれるはずです。データをnullで終了して印刷するためには、バッファからデータをコピーする必要があります。

最初にこれをテストして、コンパイラ設定を確認することをお勧めします。 Microsoftの以前のバージョンのVisual C++では、デバッグビルドは、割り当てられたメモリの周囲にフェンスポストを追加したメモリアロケータのデバッグバージョンにリンクしていました。これにより、デバッガは上書きされたメモリエラーについて報告できます。新しいバージョンがまだそれを行うかどうかはわかりませんが、リリースビルドが行わないことは知っています。

彼らに「なぜ」を伝えたい場合は、Fred @@@@@@@@のような名前を入力するとクラッシュを引き起こし、ハッカーがプログラムを乗っ取れるようにする方法を示します。

7
John Deters

afaikの最新のLinuxカーネルには実行可能なスタックがないため、通常のLinuxディストリビューションでプログラムをテストすることはできません。 (DebianマシンのAlef Oneペーパーに記載されているコードのテストで問題が発生したことを覚えています)

あなたができることは、セキュリティ設定を無効にして、そこでコードをテストするように指示するカスタムvm(いまいましい脆弱なLinuxなど)を提供することです。

要するに、解決策は、コマンドライン引数またはユーザー入力としてファイル名を取得するプログラムを作成することです。

  • ファイルを開きます
  • それからいくつかの設定を読み取ります
  • それを解析する/何か特定のものを探す
  • 関連する部分をネットワークソケットにプッシュします
  • 別のプロセスがデータを読み取り、いくつかの関連部分を印刷する必要があります。

あなたのシナリオは:

ユーザーが提供したファイルから航空会社のフライトスケジュールを読み取り、TCPソケットを介して別のプロセスにプッシュして表示するプログラムをcで作成する必要があります。

少し物事を刺激するために、すべてを処理する必要がある構造体を提供できます。

ほとんどのコードはオンラインで見つけることができ(ファイルから読み取り、ソケットに書き込み)、学生はメモリ処理を行うだけなので、簡単です。

5
ndp

プラットフォームの制約に応じて、いくつかの [〜#〜] dcom [〜#〜] を実装することをお勧めします。

DCOM呼び出しの実装には、ネットワーク呼び出し、インターフェイスの処理、マーシャリング、分散参照カウントとオブジェクトの有効期間の管理、共有メモリの安全性など、さまざまな問題の多い領域が含まれます。正しく実行された場合、低レベルのACLチェックなども含まれます。たくさんの小さなビットと複雑な構造が飛び交っています。

neverDCOMコード-クライアントまたはサーバーの呼び出し-に重大なバグがない(VBなどの「安全な」言語で実装されている場合を除く)それでもそれは一般的です)。

4
AviD