web-dev-qa-db-ja.com

サイドチャネルがなくなるように機能を変更します

与えられているのは、crackme(バイナリファイル)の一部である関数compareKeyです。適切なパスワードを見つけるために使用できるサイドチャネル攻撃(パスワードはASCIIでコード化されたazからの大小の文字、および小数で構成されます)と、この関数をどのように設計して、サイドチャネルはありませんか?

int compareKey() {
    unsigned int leng = strleng(keyInput);
    unsigned int correctLeng = strleng(correctKey);
    int i, randomTime, falseKey = 0;

    unsigned int seed = getpid() + keyInput[0];
    srand(seed);  // initialize the random seed

    if (leng != correctLeng)
        return 1;

    for (i = correctLeng-1; i >= 0; i--) {
        if (keyInput[i] != correctKey[i]) {
            usleep(500000);  // that delay will stop bruteforce attack

            falseKey = 1;
        }
    }
    randomTime = 500000 * (Rand() % 3);
    usleep(randomTime); // take that
    // and this will prevent the attacker to perform a timed attack

    return falseKey;
}

そのため、私はすでにcrackmeバイナリを実行し、長さが異なるいくつかのパスワードを入力しています。パスワードの長さが7の場合、Wrong(間違ったパスワード..)を表示するにはさらに時間がかかることがわかりました。パスワードの長さが7以外の場合は、すぐにWrongが出力されます。したがって、パスワードは長さ7である可能性が最も高く(確かにそうです!)、ここからタイミング攻撃が発生する可能性があります。上記のコードでは、2つの文字列keyInputcorrectKey)が文字ごとに比較され、現在比較されている2つの文字の違いが見つかったときに不一致が警告されます。

これまでのところ、これは正しい観測ですか?

このサイドチャネルを次のように修正できます。

def secureCompare(stringA, stringB) :
    if (sha256(A) == sha256(B))
        return True
    else
        return False
OR

def secureCompare(stringA, stringB) :
    if leng(A) != leng(B):
        return False

    result = 0
    for x, y in Zip(A, B) :
        result |= x ^ y
    return result == 0

本当によく分からないのですか? :/

4
eyesima

提案された両方の実装に問題があります。

ハッシュを比較するときはまだタイミングを気にする必要があります 、および==演算子はほぼ確実に一定の時間ではありません。

2番目の方法は2つの理由で失敗します。どちらの理由でも、攻撃者は秘密の長さを簡単に判断できます。

  1. あなたは早いうちに終わりました。
  2. Pythonの Zip は最短のイテレータの長さに切り捨てられるため、攻撃者は時刻が同じになるまで入力の長さを増やし続けることができます。
3
AndrolGenhald

最初にパスワードを静的サイズのバッファーにコピーしてから、同じコピー関数を使用して残りのバッファーに静的ゼロ文字列を入力します(それ以外の場合、コピーはサイズ情報をリークします)。その場合でも、コピーがページの境界を越える可能性があるため、サイズ情報の一部が漏洩する可能性がありますが、通常、この種のキャッシュ情報は、同じマシンから攻撃が行われた場合にのみ漏洩します。サイズを計算すると、情報が漏洩する可能性もあります(くるくる回って、面白くない)。

静的文字列には、入力の一部にできない特定の値を含める必要があります。そうしないと、静的バッファ内で何かで終わるパスワードは、短いパスワードと同じ値と比較されます(hiy | aaはhiya | aと同じです)。連結です。

別のオプションは、最初に長さを配列にコピーして、ランダム化された文字列を使用できるようにすることです(もちろん、値を比較するには同じでなければなりません)。


静的サイズのxとyをx 'とy'と名付けましょう。次に、ランダムキーを生成し、HMAC(K_r、x ')とHMAC(K_r、y')を比較します。入力の代わりにHMACがランダム化されるため、これは入力値に関する情報をリークしません比較ごとに。これには、H(K_r | x ')およびH(K_r | y')を使用することもできます。


ランダムな遅延を使用する場合は、操作の前に実行します。これにより、タイミングベースの攻撃だけを心配しているのではない場合に、操作中に電力測定を実行することが難しくなります。

2
Maarten Bodewes