メインコンテンツ

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

ハッシュ演算のソルトがありません

ハッシュされたデータはレインボー テーブル攻撃に対して脆弱

説明

この欠陥は、以下の関数においてダイジェスト コンテキストを使用するときに、データをコンテキストに 1 回しかハッシュしなかった場合または後続のすべてのハッシュ演算で null ソルトを使用した場合に発生します。ソルトとは、ハッシュ演算のセキュリティ向上のために使用するランダム データです。ハッシュ演算では、より安全なハッシュ値を生成するための入力としてソルトを利用します。

  • EVP_DigestFinal

  • EVP_DigestSignUpdate

  • EVP_DigestVerifyUpdate

  • 関数 SHA*_Final のファミリ

ハッシュ演算のソルトがありませんは、コンテキストに関して利用できる情報がなければ、欠陥を報告しません。そのような例としては、ハッシュ演算を呼び出す関数に引数としてコンテキストが渡された場合や、関数のスコープ外でコンテキストが宣言された場合が挙げられます。たとえば、以下のコード スニペットでは欠陥が報告されません。

EVP_MD_CTX ctx_global;

void foo(EVP_MD_CTX* ctx) {
//ctx passed as argument of func()
    EVP_DigestFinal(ctx, out_buf, &out_len); //no defect
}

void bar() {
// ctx_global declared outside of bar() 
    EVP_DigestFinal(&ctx_glob, out_buf, &out_len); //no defect
}

リスク

ソルトを使用せずに同じデータをハッシュすると、得られるハッシュ値も同一になります。たとえば、ユーザー パスワードをハッシュし、2 人のユーザーが同じパスワードをもつ場合、ハッシュされたパスワードも同一になります。そのようなハッシュ化は、事前計算によるレインボー攻撃に対して脆弱となります。

修正方法

データをハッシュする際にソルトを付与します。

すべて展開する

#include <openssl/evp.h>
#include <cstring>

unsigned char* out_buf;
unsigned int out_len;

void func()
{
    const char* src = "toto";
    EVP_MD_CTX ctx;

    EVP_DigestInit(&ctx, EVP_sha256());
    EVP_DigestUpdate(&ctx, src, strlen(src));
    EVP_DigestFinal(&ctx, out_buf, &out_len);
    EVP_cleanup();
}

この例では、コンテキスト ctx が安全なハッシュ アルゴリズム SHA-256 を使用して初期化され、次いで EVP_DigestUpdatesrcctx にハッシュしています。EVP_DigestUpdate の呼び出しは 1 度のみであるため、ハッシュ演算のセキュリティを向上させるためのソルトを付与することができません。その場合、EVP_DigestFinal が取得するダイジェスト値は、事前計算によるレインボー攻撃に対して脆弱となります。

修正 — データの初回ハッシュ後にソルトをコンテキストにハッシュ

1 つの修正方法として、初回のハッシュ演算後にソルトをコンテキスト ctx にハッシュします。その結果、EVP_DigestFinal が取得するダイジェスト値はより安全なものとなります。

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <cstring>

#define BUFF_SIZE_32 32

unsigned char* out_buf;
unsigned int out_len;

void func()
{
    const char* src = "toto";
    const char* salt;

    RAND_bytes((unsigned char*)salt, BUFF_SIZE_32);
    EVP_MD_CTX ctx;

    EVP_DigestInit(&ctx, EVP_sha256());
    EVP_DigestUpdate(&ctx, src, strlen(src));
    EVP_DigestUpdate(&ctx, salt, BUFF_SIZE_32);
    EVP_DigestFinal(&ctx, out_buf, &out_len);
    EVP_cleanup();
}

結果情報

グループ: 暗号化
言語: C | C++
既定値: オフ
コマンド ライン構文: CRYPTO_MD_NO_SALT
影響度: Medium

バージョン履歴

R2019b で導入