タイミング攻撃対策
タイミング攻撃とは概念を知っていたけれど、いざ書いてるときに失念してしまっていた。気付いた時にしっかりと調べて書き留めておこうと思った、という記録。
タイミング攻撃とは、2つの文字列などのbyte列の比較時にその処理時間から一致している位置を特定することができるという攻撃手法。
一般的な==など比較ではbyteごとの比較を行うため異なっているbyteに出会ったタイミングで比較を打ち切ってしまう。これによって一致しているbyte数によって処理時間が変わってくる。処理時間の差を観測することで1文字づつ一致が判定できるようになり、劇的に総当り時間が減る。
実際にネットワーク越しで通信遅延など様々なノイズがあったとしても、それが効果的であることはすでに実証されている。
対策では常に一定時間の比較を行う関数を利用する。認証などでなんらかの一致検証を行う場合は必ず利用する。
Node.js での実装例は以下。
code:vulnerable.js
if (digest !== hmacHeader) badRequest();
code:safe.js
const digestBuffer = Buffer.from(digest, "utf-8");
const hmacHeaderBuffer = Buffer.from(hmacHeader, "utf-8");
if (
digestBuffer.length !== hmacHeaderBuffer.length ||
!crypto.timingSafeEqual(digestBuffer, hmacHeaderBuffer)
) {
badRequest();
}
長さが異なる場合に crypto.timingSafeEqual は例外をthrowするため、先に棄却してしまう。
Web Crypto API にも同等の関数が用意されている。crypto.subtle.timingSafeEqual
今回の脆弱性に気づいたきっかけは、AIが書いてくれたサンプルコードにこの処理が含まれていたことからだった。とても優秀な副操縦士である。そして学びの機会にもなりとても感謝している。