c/c++バッファオーバーフロー


CおよびC++では、バッファは、通常、配列およびmalloc() およびnewのようなメモリ割り当てルーチンを用いて実現される.極めて一般的なバッファ種別は簡単な文字配列である.オーバーフローとは、バッファに割り当てられたメモリブロックにデータが追加されることを意味する.
 
ほとんどのコンピュータ言語では、新しい言語でも古い言語でも、バッファをオーバーフローさせる試みは、通常、言語自体によって自動的に検出され、ブロックされます.(たとえば、例外を起こしたり、必要に応じてバッファにスペースを追加したりします).しかし、2つの言語はそうではありません.CとC++言語です.CとC++言語は通常、残りのメモリの任意の場所に追加のデータを書き込むだけです.この場合、恐怖の結果を招く可能性があります.さらに悪いことに、CとC++で正しいコードを書くのは、常にバッファオーバーフローを一度に処理することはさらに困難である.予期せぬバッファオーバーフローを招きやすい.CとC++が非常に広く使用されていることを除いて、これらは関連のない事実である可能性がある.例えば、Red Hat Linux 7.1の86%のコード行は、CまたはC++で記述されている.したがって、言語がコードを保護してこの問題を避けることができないため、大量のコードはこの問題に対して脆弱である.
 
CとC++に付随する大量の危険関数や一般的に使用されているライブラリは、検査スペースさえできません.これらの関数のプログラムの使用は、慎重に使用しない限り、プログラムの欠陥になるため、警告信号です.これらの関数のリストを覚える必要はありません.私の本当の目的はこの問題がどんなに普遍的であるかを説明することです.これらの関数には、strcpy(3)、strcat(3)、sprintf(3)(およびその同類のvsprintf(3))およびgets(3)が含まれます.scanf()の関数セット(scanf(3)、fscanf(3)、sscanf(3)、vscanf(3)、vsscanf(3)およびvfscanf(3))は、最大長を定義していないフォーマットを使用することが容易であるため、問題を引き起こす可能性があります(信頼できない入力を読み取る場合、フォーマット「%s」を使用すると常にエラーになります).
他の危険な関数には、realpath(3)、getopt(3)、getpass(3)、streadd(3)、strecpy(3)およびstrtrns(3)が含まれる.理論的には、snprintf()は比較的安全であるべきである――現代のGNU/Linuxシステムでは確かにそうである.しかし、非常に古いUNIXとLinuxシステムは、snprintf()が実現すべき保護メカニズムを実現していない.
 
Microsoftのライブラリには、対応するプラットフォームで同種の問題を引き起こす他の関数(wcscpy()、_tcscpy()、_mbscpy()、wcscat()、_tcscat()、_mbscat()およびCopyMemory()を含む)もあります.MicrosoftのMultiByteToWideChar()関数を使用すると、文字数として最大サイズが必要な一般的な危険エラーもあります.ただし、プログラマは、このサイズをバイト単位で計算することがよくあります.(より一般的な必要性)、結果としてバッファオーバーフロー欠陥が生じる.
もう1つの問題は、CおよびC++が整数に対して非常に弱いタイプの検査を有し、これらの整数を操作する問題は一般的に検出されないことである.プログラマにすべての問題検出作業を手作業で行うように要求されるため、それらの整数を何らかの利用可能な方法で正しく操作することは容易である.特に、バッファの長さを追跡したり、コンテンツの長さを読み取ったりする必要がある場合は、通常このような状況です.しかし、シンボルのある値を使用してこの長さ値を格納するとどうなるのでしょうか.攻撃者は「負の値」にし、データを実際に大きな正の値と解釈しますか.数値値が異なるサイズに変換されると、攻撃者はこの操作を利用しますか?数値オーバーフローは利用できますか?整数を処理する方法でプログラムの欠陥が発生する場合があります.
 
バッファオーバーフローに対する簡単な解決策は、バッファオーバーフローを防止できる言語を使用することである.結局、CとC++を除いて、ほとんどの高級言語はバッファオーバーフローを効果的に防止する内蔵メカニズムを持っている.
 
gets()、strcpy()、strcat()、sprintf()、fscanf()、scanf()、vsprin tf()、realpath()、getopt()、getpass()、streadd()、strecpy()、strtrtrns()などの文字列処理時にbuffer境界をチェックしない関数の使用を防止し、execlp()およびexecvp()の使用を回避します.システム()とpopen()システムで呼び出さないでください.