ソフトウェアの脆弱性の原則

バッファオーバーフローの脆弱性

バッファ:プログラムの実行前に一部のメモリスペースが予約されています。これらのスペースは、I / Oデータを一時的に保存するために使用されます。
バッファオーバーフロー:コンピュータによってバッファに入力されたデータがバッファ自体の容量を超え、正当なデータが上書きされます。
バッファのメモリスペースとその割り当て形式に応じて、スタックオーバーフローとヒープオーバーフローの2つのタイプに分けることができます。

スタックオーバーフロー

スタック:ファーストイン、ラストアウトの原則に準拠する基本的なデータ構造。
スタックオーバーフロー:スタックは低いアドレスに向かって成長し、スタック内の変数は地質学的方向に向かって成長します。したがって、スタック内の変数に割り当てられた値が割り当てられた最大バッファーサイズを超えると、前のプッシュが上書きされます。スタックへの戻りアドレスは、関数が戻るときにエラー、つまりスタックオーバーフローを引き起こします。
次のコードのオーバーフローの理由は、64バイトのデータがわずか8バイトの長さでtestBuf配列に強制的にコピーされ、スタックオーバーフローが発生したためです。ここに写真の説明を挿入

ヒープオーバーフロー

ヒープ:基本的なデータ構造。ヒープはツリー構造であり、正確には完全なバイナリツリーです。プログラムの実行中に、ヒープは動的に割り当てられたメモリを提供できるため、プログラムはサイズが不明なメモリに適用できます。ヒープは実際には、プログラムの仮想アドレス空間の連続した線形領域であり、低いアドレスから高いアドレスに成長します。通常、ヒープを管理するプログラムの一部をヒープマネージャーと呼びます。
ヒープオーバーフロー:ヒープ内の変数には、割り当てられたスペースのサイズを超える値が割り当てられ、ヒープリンクリストの後続のリンクリストデータが上書きされます。
さまざまな環境でのヒープの実装が完全に同じではないため、ヒープオーバーフローは比較的複雑です。
攻撃者が実行プロセスを直接制御できるようにするリターンアドレスがヒープにないため、通常、ヒープオーバーフローを介してEIPを直接制御することはできません。
ここに写真の説明を挿入

予防

スタックオーバーフローによって引き起こされる可能性のあるコンピュータセキュリティの問題については、通常、次の予防措置があります。

  1. 正しいルールに従ってコードを書くことが義務付けられています
  2. オペレーティングシステムはバッファを実行不能にするため、攻撃者が攻撃コードを埋め込むのを防ぎます。ただし、攻撃者は必ずしもコードを埋め込んで攻撃を実装するわけではないため、この方法にはまだいくつかの弱点があります。
  3. コンパイラの境界チェックを使用して、バッファを保護します。この方法では、バッファオーバーフローが不可能になり、バッファオーバーフローの脅威が完全に排除されますが、パフォーマンスが低下するなどのコストがかかります。
  4. プログラムポインタの整合性チェック。このメソッドは、ほとんどのバッファオーバーフロー攻撃を防ぐことができます。この方法は、プログラムがポインターを使用する前に、ポインターの内容が変更されたかどうかを確認することです。

通常、コードはスタックバッファを設定する必要があります。スタックの動作ステータスを検出し、スタックオーバーフロー検出アルゴリズムを設定するのが最適です。再帰によるスタックオーバーフローの場合は、ループ処理を使用できます。

整数オーバーフローの脆弱性

コンピューターでは、整数は特定の変数タイプです。異なるCPUアーキテクチャのコンパイラで処理した後、整数とポインタが占めるバイトは一般に同じです。したがって、32ビットシステム(x86など)では整数が32ビットを占め、64ビットシステム(SPARCなど)では整数が64ビットを占めます。
ただし、これだけでは不十分です。このように負の数を表すことはできないため、メカニズムを導入する必要があります。つまり、変数の最上位ビットを介して値の正または負を決定します。最高位が1の場合、この変数は負の数として解釈されます。0に設定されている場合、この変数は正の数として解釈されます。
C言語では、基本的なデータタイプには、short integer short、integer int、long integer longがあります。各データタイプは、符号付きと符号なしの数値に分割することもできます。inta= 0のような式を使用するようにしています。デフォルトでは、符号付き整数データを定義します。符号なしの数値の場合、unsigned int a = 0として明示的に宣言する必要があります。各データタイプには、対応する範囲があります。
整数オーバーフローは、原因の観点から、ストレージオーバーフロー、計算オーバーフロー、およびシンボリック問題の3つのカテゴリに分類できます。

ストレージオーバーフロー

ストレージオーバーフロー:さまざまなデータタイプを使用して整数を格納することが原因です。
len1とlen2のデータ型の長さが同じではないため、割り当て操作中にlen2がlen1のすべてのビットに対応することはできません。
ここに写真の説明を挿入
タイプshortのlen2をlen1に割り当てると、下位16ビットしかカバーできません。
ここに写真の説明を挿入

操作オーバーフロー

動作中の整数オーバーフローが最も一般的な状況です。多くのよく知られている脆弱性は、この整数オーバーフローによって引き起こされます。原則として、整数変数の動作中に整数変数の境界範囲は考慮されません。の値がストレージスペースを超えています。
固定点コンピューターと浮動小数点コンピューターでは、オーバーフローとアンダーフローの概念はまったく同じではありません。固定小数点コンピュータでは、正の方向からの数値の範囲を超えることをオーバーフローと呼び、負の方向からの数値の範囲を超えることをアンダーフローと呼びます。浮動小数点コンピュータでは、浮動小数点数の表現範囲は主に注文コードによって決定されます。数字の符号が正か負かに関係なく、注文コードが正の方向から注文コードの表示範囲を超える場合、オーバーフローと呼ばれます。注文コードが負の方向から注文コードの表示範囲を超える場合、またはマンティッサが「0」の場合、総称してアンダーフローと呼ばれます。一般的に、コンピュータはエラー情報を出力せずに浮動小数点数のアンダーフローを自動的に「0」として扱います。オーバーフローが発生している間、コンピュータは「オーバーフロー割り込み」を生成してオーバーフローエラーメッセージを出力するか、停止します。プログラムの操作。

象徴的な問題

符号の問題:整数は符号付き整数と符号なし整数に分けられます。一般に、長さ変数には符号なし整数が必要です。符号を無視すると、オーバーフローが発生する可能性があります。
ブロックコーディング:データを格納するためのバッファーを割り当てます。送信されたデータのサイズが不明な場合、クライアントはネゴシエートされたブロックサイズでデータをサーバーに送信します。
Apacheサーバーは、ブロックエンコーディングのサポートを提供し、符号付き変数を使用してブロック長を格納し、固定サイズのスタックバッファーを割り当ててブロック長を格納します。ブロックデータをバッファにコピーする前に、Apacheはブロック長をチェックします。ブロック長がバッファ長よりも大きい場合、Apacheはバッファ長までのデータのみをコピーします。それ以外の場合は、ブロック長に従ってデータをコピーします。ただし、チェック中の比較のために、ブロック長は符号なしに変換されませんでした。したがって、攻撃者がブロック長を負の値に設定すると、上記のセキュリティチェックはバイパスされます。

防ぐ方法

整数オーバーフローの脆弱性を防ぐ方法:

  1. 適切なデータタイプを使用する前に、最大入力と最小入力を決定するなど、特別なデータ入力に関する認識を形成します。
  2. 2つの正の数を追加しないようにしてから、結果を比較してください。上記の例は次のように変更する必要があります。
  3. 変数を使用してメモリに適用したり、配列の添え字として使用したりする場合は、範囲外の監視に注意してください。

整数オーバーフローの脆弱性は、主にプログラマーの悪い習慣と怠慢が原因であり、安全なプログラミング習慣を身に付け、変数の割り当てを厳密にチェックします。

UAFの脆弱性

UAFの脆弱性:ヒープメモリの一部が解放されて使用されます。再度使用される参照:ポインタが存在します(ぶら下がっているポインタが参照されます)。
次の3つの状況に分けられます。

  1. メモリブロックが解放された後、対応するポインタがNULLに設定され、再び使用されると、自然なプログラムがクラッシュします。
  2. メモリブロックが解放された後、対応するポインタはNULLに設定されず、次に使用される前に、このメモリブロックを変更するコードがないため、プログラムは正常に実行される可能性があります。
  3. メモリブロックが解放された後、対応するポインタはNULLに設定されませんが、次に使用される前に、一部のコードがこのメモリを変更するため、プログラムがこのメモリを再び使用すると、次のように表示される可能性があります。奇妙な質問。

ぶら下がりポインター:有効または有効な(つまり、ポインターの意味と矛盾する)オブジェクトを指さないタイプのポインター。たとえば、オブジェクトのポインタは、オブジェクトが解放またはリサイクルされたが、ポインタが変更されておらず、解放されたメモリを実行している場合、このポインタはダングリングポインタと呼ばれます。

簡単に言うと、最初に要求されたメモリスペースはリリース後に再利用されないため、次回メモリが要求されたときにメモリブロックが再び使用され、前のメモリポインタが変更されたメモリにアクセスできます。

具体的なプロセスを図に示します。AはBCDの3つのサブ機能を連続して呼び出し、BはAの特定のリソースを解放し、Dは厳密な判断を下しません。BがAのリソースを解放した後も、Aのリソース(ポインタなど)を参照します。 Dは危険なぶら下がりポインターを参照します。したがって、useメソッドは次のとおりです。AがBを呼び出すと、BはAのポインタを解放し、Cを実行し、Cはメモリ割り当てをすばやく適用し、解放されたばかりのスペースを占有しようとして、このメモリを制御します。Dが呼び出されます。修飾され、解放されたポインタが呼び出され、ポインタに対応するメモリ空間が実際にCで再利用され、脆弱性の悪用につながります。
ここに写真の説明を挿入
UAFの脆弱性を防ぐ方法は、その原則から、UAFの脆弱性はポインターの不適切な使用によって引き起こされること、つまり、ポインターが解放されて後続の関数によって呼び出されることを知ることができます。したがって、プログラミングプロセスでは、開発者はポインターを使用する前にポインターが有効かどうかを判断する必要があります。 。

おすすめ

転載: blog.csdn.net/weixin_43916678/article/details/107180322