INT04-C. 信頼できない入力源から取得した整数値は制限する
信頼できない入力源から取得したすべての整数値について、上限と下限を特定できるかどうか見極めること。もし上限と下限を特定できるのなら、インターフェイスでその制限を強制すること。過度に大きなあるいは小さな整数値を制限することで、オーバーフロー、切り捨て、その他の範囲エラーを防ぐことができる。また、入力値に関する問題を発見、修正する方が、内部エラーをたどって間違った入力値を発見し修正するよりも容易である。
違反コード
以下のコード例では、length
はユーザが提供する環境変数で与えられる値であり(その値は信頼できない)、動的に割り当てる配列 table
のサイズとして使用されている。「INT30-C. 符号無し整数の演算結果がラップアラウンドしないようにする」に沿って、符号なし整数のラップアラウンドは発生しないようにしているが、配列のサイズの上限をチェックしておらず、過度に大量のメモリを確保させられる可能性がある。
char** create_table(void) { const char* const lenstr = getenv("TABLE_SIZE"); const size_t length = lenstr ? strtoul(lenstr, NULL, 10) : 0; if (length > SIZE_MAX / sizeof(char *)) return NULL; /* 呼び出し元にエラーを返す */ const size_t table_size = length * sizeof(char *); char** const table = (char **)malloc(table_size); if (table == NULL) return NULL; /* 呼び出し元にエラーを返す */ /* table を初期化する... */ return table; }
length
の値はユーザがコントロールするため、その値のせいで大きなメモリブロックが割り当てられたり、malloc
呼び出しが失敗させられたりする可能性がある。エラー処理の実装如何によっては、サービス運用妨害攻撃(DoS)やその他のエラーにつながるかもしれない。
適合コード
以下の適合コードでは、length
の許容範囲を [1, MAX_TABLE_LENGTH]
としている。length
変数は size_t
として宣言されており、これは定義により符号無し整数である。これにより、length
が負の値でないかチェックする必要はない。(「INT01-C. オブジェクトのサイズを表現するすべての整数値に rsize_t もしくは size_t を使用する」を参照。)
enum { MAX_TABLE_LENGTH = 256 }; char** create_table(void) { const char* const lenstr = getenv("TABLE_SIZE"); const size_t length = lenstr ? strtoul(lenstr, NULL, 10) : 0; if (length == 0 || length > MAX_TABLE_LENGTH) return NULL; /* 呼び出し元にエラーを返す */ const size_t table_size = length * sizeof(char *); char** const table = (char **)malloc(table_size); if (table == NULL) return NULL; /* 呼び出し元にエラーを返す */ /* table を初期化する... */ return table; }
length == 0
をチェックすることで、ゼロより大きい領域が割り当てられることを保証している。(「MEM04-C. サイズ 0 のメモリ割り当てを行わない」を参照。)
違反コード
以下のコード例では、信頼できない整数 color_index
が配列 table のインデックスとして使用されている。
const char *table[] = { "black", "white", "blue", "green" }; const char *set_background_color(void) { int color_index; GET_TAINTED_INTEGER(int, color_index); const char *color = table[color_index]; /* 違反 */ /* ... */ return color; }
適合コード
以下の適合コードでは、color_index
の許容範囲を [1, MAX_COLOR_INDEX]
としている。
enum { MAX_COLOR_INDEX = 3 }; const char *table[] = { "black", "white", "blue", "green" }; const char *set_background_color(void) { int color_index; GET_TAINTED_INTEGER(int, color_index); if (color_index < 0 || colo_index > MAX_COLOR_INDEX) return NULL; /* 呼び出し元にエラーを返す */ const char *color = table[color_index]; /* ... */ return color; }
リスク評価
整数値の範囲を強制しないとサービス運用妨害攻撃(DoS)につながる恐れがある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
INT04-C |
低 |
中 |
高 |
P2 |
L3 |
関連するガイドライン
CERT C++ Secure Coding Standard | INT04-CPP. Enforce limits on integer values originating from untrusted sources |
ISO/IEC TS 17961 (ドラフト) | Tainted, potentially mutilated, or out-of-domain integer values are used in a restricted sink [taintsink] |
参考資料
[Seacord 2013] | Chapter 5, "Integer Security" |
翻訳元
これは以下のページを翻訳したものです。
INT04-C. Enforce limits on integer values originating from untrusted sources (revision 77)