メインコンテンツ

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

疑似乱数発生器が脆弱です

暗号法的に脆弱な疑似乱数発生器を使用

説明

この欠陥は、暗号法的に脆弱な疑似乱数発生器 (PRNG) ルーチンが使用された場合に発生します。

このチェッカーによってフラグが付けられる暗号法的に脆弱なルーチンのリストには次のものが含まれます。

  • rand, random

  • drand48lrand48mrand48erand48nrand48jrand48 および drand48_r などの同等の _r 付きルーチン

  • RAND_pseudo_bytes

リスク

こうした暗号法的に脆弱なルーチンは予測可能であり、セキュリティ目的で使用してはなりません。予測可能な乱数値で実行フローを制御する場合、プログラムは悪意のある攻撃に対し脆弱となります。

修正方法

CryptGenRandom (Windows) や OpenSSL/RAND_bytes (Linux/UNIX) など、より暗号法的に健全な乱数発生器を使用します。

すべて展開する

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

volatile int rd = 1;
int main(int argc, char *argv[])
{   
    int j, r, nloops;
    struct random_data buf;
    int i = 0;
    
    nloops = rand();
    
    for (j = 0; j < nloops; j++) {
        if (random_r(&buf, &i))
            exit(1);
        printf("random_r: %ld\n", (long)i);
    }
    return 0;
}

この例では、関数 rand()random_r() を使用して乱数を生成しています。これらの関数をセキュリティ目的で使用すると、こうした PRNG は悪意のある攻撃の発生源となる可能性があります。

修正 — より強固な PRNG を使用

1 つの修正方法として、脆弱な PRNG を、より強固な乱数発生器に置き換えます。

#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>

volatile int rd = 1;
int main(int argc, char* argv[])
{   
    int j, r, nloops;
    unsigned char buf;
    unsigned int seed;
    int i = 0;
    
    if (argc != 3) 
    {
        fprintf(stderr, "Usage: %s <seed> <nloops>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    
    seed = atoi(argv[1]);
    nloops = atoi(argv[2]);
    
    for (j = 0; j < nloops; j++) {
        if (RAND_bytes(&buf, i) != 1)
            exit(1);
        printf("RAND_bytes: %u\n", (unsigned)buf);
    }
    return 0;
}

結果情報

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

バージョン履歴

R2015b で導入