JPCERT コーディネーションセンター

INT04-C. 信頼できない入力源から取得した整数値は制限する

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)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter