24

ZendFrameworkのHTTPAuthライブラリでこのコードに出くわしました。より安全にするために、特別な文字列比較関数を使用しているようです。ただ、コメントがよくわかりません。この関数が実行するよりも安全である理由を誰かが説明でき$a == $bますか?

/**
 * Securely compare two strings for equality while avoided C level memcmp()
 * optimisations capable of leaking timing information useful to an attacker
 * attempting to iteratively guess the unknown string (e.g. password) being
 * compared against.
 *
 * @param string $a
 * @param string $b
 * @return bool
 */
protected function _secureStringCompare($a, $b)
{
    if (strlen($a) !== strlen($b)) {
        return false;
    }
    $result = 0;
    for ($i = 0; $i < strlen($a); $i++) {
        $result |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $result == 0;
}
4

1 に答える 1

37

彼らはタイミング攻撃を防ごうとしているようです。

暗号化では、タイミング攻撃はサイドチャネル攻撃であり、攻撃者は暗号化アルゴリズムの実行にかかる時間を分析することにより、暗号システムを侵害しようとします。コンピューターのすべての論理演算は実行に時間がかかり、時間は入力によって異なる場合があります。各操作の時間を正確に測定することで、攻撃者は入力に逆戻りする可能性があります。

基本的に、正しいパスワードと間違ったパスワードを比較するのに時間が異なる場合は、タイミングを使用して、正しく推測したパスワードの文字数を把握できます。

非常に欠陥のある文字列比較を考えてみましょう(これは基本的に通常の文字列等価関数であり、明らかなwait追加があります)。

function compare(a, b) {
    if(len(a) !== len(b)) { 
        return false;
    }
    for(i = 0; i < len(a); ++i) {
        if(a[i] !== b[i]) {
            return false;
        }
        wait(10); // wait 10 ms
    }
    return true;
}

パスワードを指定すると、(一貫して)1つのパスワードにはある程度の時間がかかり、別のパスワードには約10ミリ秒長くかかります。これはあなたに何を伝えますか?これは、2番目のパスワードの文字数が最初のパスワードより1文字多いことを意味します。

これにより、映画のハッキングを行うことができます。一度に1文字ずつパスワードを推測します(これは、考えられるすべてのパスワードを推測するよりもはるかに簡単です)。

現実の世界では、他の要因が関係しているため、現実の世界のランダム性を処理するには、パスワードを何度も試す必要がありますが、明らかに時間がかかるまで1文字ごとのパスワードを試し、その後2つから始めることができます。文字パスワードなど。

この関数にはまだ小さな問題があります:

if(strlen($a) !== strlen($b)) { 
    return false;
}

タイミング攻撃を使用してパスワードの正しい長さを把握できるため、短いパスワードや長いパスワードをわざわざ推測する必要がありません。一般に、最初にパスワードをハッシュしたいので(同じ長さの文字列が作成されます)、彼らはそれが問題であるとは考えていなかったと思います。

于 2012-05-14T02:13:12.403 に答える