web-dev-qa-db-ja.com

C#でバッファオーバーフローの悪用は可能ですか?

C#プログラムがマネージ.NETコードのみを使用すると仮定すると、そのプログラム内にバッファオーバーフローのセキュリティ脆弱性が存在する可能性はありますか?もしそうなら、そのような脆弱性はどのようにして起こり得ますか?

30
poke

はい、しかしそれらは生産するのがはるかに困難です。バッファオーバーフローが発生する可能性があるのは、特定の安全でない構造を使用した場合のみであり、「通常の」C#コードでは使用できません。信頼性を下げてコードを実行している場合、メモリ破損コードはまったく起こり得ないはずです。

バッファオーバーフローのいくつかの可能性:

  1. ポインタを許可するunsafeキーワードの使用。安全でないコードは、cまたはc ++のポインターベースのコードと同じくらい簡単に誤解されます。
  2. Marshalクラスのメソッドなど、安全でないAPIを使用する
  3. (Monoのみ)配列の範囲チェックを無効にできます(安全性とパフォーマンスのトレードオフ)。

バッファオーバーフローとは別に、メモリを破壊する他の方法もいくつかあります。

  1. StructLayoutKind.Explicit
  2. ネイティブ相互運用シグネチャが間違っています

(ランタイム自体はC++で記述されているため、ランタイムのバグによりメモリが破損したり、バッファがオーバーフローする可能性がありますが、この質問の範囲外と見なします)

49
CodesInChaos

はい、安全でない環境では:

unsafe void bufferOverflow(string s)
{
    char* ptr = stackalloc char[10];

    foreach (var c in s)
    {
        *ptr++ = c; // Bufferoverflow if s.Length > 10
    }
}

これをコンパイルするには、「安全でないコードを許可する」をチェックする必要があります。

配列を使用した従来のバッファオーバーフローはできません。安全であることが保証されていない限り(CLR)、配列にアクセスする前に境界チェックを行います。

19
Lasse Espeholt

unsafe キーワードを使用する場合のみ。

5
Chris

絶対的な意味で、はい、.NETランタイムのバグが原因でバッファの悪用が可能です。ただし、.NETは、これらの種類の問題からほとんどのエンドユーザーコード(「安全でない」使用を除く)を防止するため、実際にはリスクが低くなります。

実際には、このような問題のほとんどは、マネージコードから呼び出されるネイティブコール(COM dllなど)から発生します。

5
seand