与えられているのは、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つの文字列keyInput
とcorrectKey
)が文字ごとに比較され、現在比較されている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
本当によく分からないのですか? :/
提案された両方の実装に問題があります。
ハッシュを比較するときはまだタイミングを気にする必要があります 、および==
演算子はほぼ確実に一定の時間ではありません。
2番目の方法は2つの理由で失敗します。どちらの理由でも、攻撃者は秘密の長さを簡単に判断できます。
最初にパスワードを静的サイズのバッファーにコピーしてから、同じコピー関数を使用して残りのバッファーに静的ゼロ文字列を入力します(それ以外の場合、コピーはサイズ情報をリークします)。その場合でも、コピーがページの境界を越える可能性があるため、サイズ情報の一部が漏洩する可能性がありますが、通常、この種のキャッシュ情報は、同じマシンから攻撃が行われた場合にのみ漏洩します。サイズを計算すると、情報が漏洩する可能性もあります(くるくる回って、面白くない)。
静的文字列には、入力の一部にできない特定の値を含める必要があります。そうしないと、静的バッファ内で何かで終わるパスワードは、短いパスワードと同じ値と比較されます(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')を使用することもできます。
ランダムな遅延を使用する場合は、操作の前に実行します。これにより、タイミングベースの攻撃だけを心配しているのではない場合に、操作中に電力測定を実行することが難しくなります。