システムやブラウザー、またはプログラムが更新されたときに、攻撃者が偽造された Web サイトを使用してコンピューターでコードを実行したり、慎重に偽造されたパケットでコンピューターを攻撃したりする可能性があるバグが修正されたことが常に変更ログで読み取られます。
頻繁に読むということは、どのプログラムにも同様の脆弱性が存在する可能性があることを意味します... 何が原因でしょうか? 同様の問題を防ぐためにプログラムを設計する方法は?
システムやブラウザー、またはプログラムが更新されたときに、攻撃者が偽造された Web サイトを使用してコンピューターでコードを実行したり、慎重に偽造されたパケットでコンピューターを攻撃したりする可能性があるバグが修正されたことが常に変更ログで読み取られます。
頻繁に読むということは、どのプログラムにも同様の脆弱性が存在する可能性があることを意味します... 何が原因でしょうか? 同様の問題を防ぐためにプログラムを設計する方法は?
バグがエクスプロイトの機会を生み出す方法の一例:
プログラムに、文字配列のデータを変更するサブルーチンがあるとします。配列が特定のサイズであるか、配列に特定の文字が含まれている場合、サブルーチンが誤って文字配列の末尾を超えて書き込むというバグも含まれているとします。
これ自体は大きなチャンスとは思えませんが、実行がサブルーチンに到達する方法や、実装およびコンパイル方法のその他のアーティファクトによっては、任意のコードを実行するための踏み台として使用される可能性があります。
従来のプログラミング (C、C++) では、多くの場合、文字配列 (バッファー) がプログラム スタックに格納されます。スタックは、小さな一時データ用の非常に高速で簡単なメモリ割り当てです。
スタックに保存されるもう 1 つのことは、関数呼び出しのリターン アドレスです。これは、この関数が終了したときに返されるコード アドレスです。
これで、災害を作成するために必要なすべてのピースが揃いました: このサブルーチンに適切なデータを渡してスタックを上書きし、データから遠く離れていないスタック上にある関数の戻りアドレスを上書きするのに十分に上書きできる場合関数が終了したときにプログラムの実行が戻る場所を変更する可能性があります。呼び出し元に戻る代わりに、Halt() または Format() または PhoneHome() に「戻る」(実際にはジャンプする) ようにすることもできます。この時点で、現在のプロセスによって参照される任意のライブラリまたは DLL 内の任意の関数にアクセスできます。
これは、任意実行エクスプロイトの一例にすぎません。そのようなパターンは数十あります。
この特定のエクスプロイトを阻止する最も簡単な方法は、コードがデータ バッファーの境界を尊重するようにすることです。ほとんどのコンパイラでは、これは範囲チェックまたは同様のランタイム チェックをオンにすることを意味します。コンパイラは、配列内のメモリ位置にアクセスする前に、配列のインデックス値が範囲内にあることを検証するコードを出力します。
最初の最も重要なルールは、「誰も信用しない」です。
鍵は「防御的プログラミング」です。関数がパラメーターを受け取ることができる最も悪質で不正な方法を常に調べてから、それを回避するように計画してください。相手側でコードを書いたからといって、渡された内容の説明を信頼できると思い込まないでください。これは、エンドユーザーの手にあるすべてのコードについて二重に当てはまります。クライアントは敵の手にあります。
この考え方を徹底的に採用すれば、攻撃に耐える準備が整います。しかし、間違いを犯すことはありますが、間違いは誰にでもあります。間違いに対応し、顧客のために更新プロセスを用意する必要があります。
The Shellcoder's Handbook: Discovering and Exploiting Security Holes (ISBN 978-0470080238) という本があり、さまざまな種類の悪用 (スタック オーバーフロー、ヒープ オーバーフロー、SQL インジェクションなど) について詳しく説明しています。
この問題については「グーグル」の優れたソースがありますが、要するに、すべての呼び出し (関数呼び出し、メソッド呼び出しなど) を安全にする必要があります。安全とは、受信データを適切なサイズに切り捨て、「評価」しないなどを意味します。
可能な攻撃の数は非常に多いです。最新情報を把握するためにBugtraqを読むことをお勧めします。
お役に立てれば!