ARR33-C. コピーは必ず十分なサイズの記憶領域に対して行われることを保証する
十分なサイズを持たない配列にデータをコピーすると、バッファオーバーフローが生じる。このようなエラーを防止するには、コピー先の配列のサイズに応じてコピーするデータを制限するか、コピー先として、データを保持するのに十分なサイズの配列を確保する必要がある。
十分なサイズを持たないバッファへコピーすることが原因で作り込まれる脆弱性には、null 終端バイト文字列(NTBS)が関連するものが多い。NTBS が関係する具体例については「STR31-C. 文字データと null 終端文字を格納するために十分な領域を確保する」を参照のこと。
違反コード
たとえば memcpy() 関数 のようなサイズ引数をとりコピーを制限する関数を適切に使用しないと、バッファオーバーフローが発生する可能性がある。下記の違反コード例では、memcpy() を使って、整数配列が src から dest にコピーされる。関数 func() の関数原型は、第一引数が const int の配列であり、第二引数が配列のサイズではなく配列境界(すなわち、配列中の要素の数)を示す。
プログラマは、num_elem と sizeof(int) を乗算し、src 配列のサイズを正しく計算するが、コピー元配列がコピー先配列より小さいことを確認していない。num_elem が 256 よりも大きいと、バッファオーバーフローが発生する。また、num_elem が大きすぎると、乗算がラップアラウンドする可能性がある(「INT30-C. 符号無し整数の演算結果がラップアラウンドしないようにする」を参照)。ラップアラウンドが発生すると、積が予想よりも小さくなり、memcpy() がコピーするメモリサイズが予想よりもはるかに小さくなる。
#include <string.h>
enum { WORKSPACE_BOUND = 256 };
void func(const int *src, size_t num_elem) {
int dest[WORKSPACE_BOUND];
memcpy(dest, src, num_elem * sizeof(int));
}
適合コード (境界検査)
コピーする文字数は、コピー先バッファのサイズに基づいて制限すべきである。下記の適合コードは、コピーされる要素の数がコピー先配列の境界を超えないことを確認するためのチェックを追加している。
#include <string.h>
enum { WORKSPACE_BOUND = 256 };
void func(const int *src, size_t num_elem) {
int dest[WORKSPACE_BOUND];
if (num_elem > WORKSPACE_BOUND) {
/* エラー処理 * /
}
memcpy(dest, src, sizeof(int) * num_elem);
}
この適合コードは、乗算によるラップアラウンドを考慮していない。これは、num_elems が 256 未満になることが保証されているからである。
適合コード (動的割り当て)
別の方法として、コピー先バッファ dest 用のメモリを動的に割り当てることで、コピー元バッファ src のデータを十分保持できる大きさを確保する方法もある。下記の適合コードでは num_elem がとりうる範囲は保証されていないため、乗算でのラップアラウンドをチェックする必要がある。
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
void func(const int *src, size_t num_elem) {
int *dest;
if (num_elem > SIZE_MAX / sizeof(int)) {
/* 整数値オーバーフローの処理 */
}
dest = (int *)malloc(sizeof(int) * num_elem);
if (dest == NULL) {
/* メモリ確保に失敗 - リカバー */
}
memcpy(dest, src, sizeof(int) * num_elem);
free(dest);
}
リスク評価
データを保持するために十分なサイズを持たないバッファにデータをコピーすると、バッファオーバーフローが生じる。攻撃者はこれを悪用し、任意のコードを実行できるかもしれない。
|
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
|---|---|---|---|---|---|
|
ARR33-C |
高 |
高 |
中 |
P18 |
L1 |
自動検出
|
ツール |
バージョン |
チェッカー |
説明 |
|---|---|---|---|
|
|
|
|
|
| Coverity | 6.5 | BUFFER_SIZE | 実装済み |
|
5.0 |
|
CERT C Rule Pack を使ってこのルールの違反を検出できる。 |
|
| V. 9.1 |
ABR |
|
|
| V. 3.1.1 |
|
|
関連するガイドライン
| CERT C セキュアコーディングスタンダード | STR31-C. 文字データと null 終端文字を格納するために十分な領域を確保する INT30-C. 符号無し整数の演算結果がラップアラウンドしないようにする |
| CERT C++ Secure Coding Standard | ARR33-CPP. Guarantee that copies are made into storage of sufficient size |
| ISO/IEC TR 24772:2013 |
Buffer Boundary Violation (Buffer Overflow) [HCB] |
| MITRE CWE | CWE-119, Failure to constrain operations within the bounds of an allocated memory buffer |
参考資料
| [Seacord 2013] | Chapter 2, "Strings" |
翻訳元
これは以下のページを翻訳したものです。
ARR33-C. Guarantee that copies are made into storage of sufficient size
