メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

予測可能なシードによる予測可能な乱数出力です

シード ルーチンで予測可能なシードが使用され、出力が予測可能になっている

説明

この欠陥は、非定数だが予測可能なシードと一緒に標準乱数発生器関数が使用された場合に発生します。予測可能なシード発生器には、timegettimeofdaygetpid などがあります。

チェッカーは、以下の乱数発生器関数を使用してこの問題を検出します。

  • srandsrandominitstate などの C 標準ライブラリ関数

  • std::linear_congruential_engine<>::seed()std::mersenne_twister_engine<>::seed() などの C++ 標準ライブラリ関数 (およびこれらのクラス テンプレートのコンストラクター)

リスク

予測可能なシード値を乱数発生に使用すると、その乱数も予測可能になります。プログラムの動作がわかると、ハッカーはプログラムを中断できます。

修正方法

別の関数を使用して、予測しにくいシードを生成します。

また、シードを必要としない別の乱数発生器を使用することもできます。たとえば、Windows® API の関数 rand_s は、既定でそれ自体にシードします。システム時間、スレッド ID、システム カウンター、メモリ クラスターなど、システム全体からの情報が使用されます。こうした情報はよりランダムであり、ユーザーはこれにアクセスできません。

標準乱数ルーチンの一部は本質的に暗号面で脆弱なため、セキュリティ保護の目的では使用しないでください。

すべて展開する

#include <stdlib.h>
#include <time.h>

void seed_rng(int seed)
{
    srand(seed);
}

int generate_num(void)
{
    seed_rng(time(NULL) + 3);
    /* ... */
}

この例では srand を使用し、seed にシードを指定して乱数発生器を起動します。しかし、seed は関数 time によって生成されるため、予測可能です。そのため、攻撃者は srand によって生成される乱数を予測できます。

修正 — 別の乱数発生器を使用

1 つの修正方法として、シードを必要としない乱数発生器を使用します。次の例では rand_s を使用しています。


#define _CRT_RAND_S

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int generate_num(void)
{
    unsigned int number;
    errno_t err;
    err = rand_s(&number);

    if(err != 0)
    {
        return number;
    }
    else
    {
        return err;
    }
}

結果情報

グループ: セキュリティ
言語: C | C++
既定値: オフ
コマンド ライン構文: RAND_SEED_PREDICTABLE
影響度: Medium

バージョン履歴

R2015b で導入