レインボーテーブル攻撃とは(*コードによる実演あり)
レインボー攻撃とは
レインボー攻撃とは、レインボーテーブルを使ってハッシュ化されたデータを解読する攻撃である。アカウントを乗っ取る目的として、パスワード解読に使われるパスワードクラックの一つとして知られる。
ハッシュ化
まずハッシュ化とは、「ハッシュ関数」というアルゴリズムによって、平文をハッシュ値に書き換えることである。(例:Password123という平文から、43nfneo43jofde31sdwというハッシュ値へ書き換える)
ハッシュ化と暗号化の違い
ハッシュ化されたパスワードは、暗号化されたパスワードとは異なり、データを元に戻すことができない。一方で、暗号化されたパスワードは、還元関数によって複合化できる。(例:43nfneo43jofde31sdwというハッシュ値から、Password123という平文へ複合化できない)
具体的手法
攻撃者は、レインボーテーブルにより、パスワードのハッシュ値から元のパスワードを割り出すことができる。レインボーテーブルでは、ハッシュ値と平文はペアになっており、ハッシュ関数を変更しない限り、平文に対するハッシュ値は常に同じである。そのため、攻撃者は大量のパスワード候補を準備しハッシュ化し、平文とハッシュ値の対応表を作る。この対応表から、ハッシュ値の元の値を割り出す攻撃をレインボー攻撃と呼ぶ。
コードによる実演
下記のようなシーンを想定しよう。攻撃者は、ユーザ情報を取得したが、パスワードはハッシュ化されているのでわからない。攻撃者はアカウントを乗っ取るため、ハッシュ化前のパスワードを取得する必要があるので、まずレインボーテーブルを作る必要がある。レインボーテーブルで、「ハッシュ化前:ハッシュ化後」のパスワードの対応表を作ることができれば、ハッシュ値を参照し平文のパスワードを取得できる。そのために、「よく使われるパスワードリスト」を取得している。
# よく使われるパスワードリストをnist_badに格納
with open('nist_10000.txt', newline='') as bad_passwords:
nist_bad = bad_passwords.read().split('\n')
# ユーザ情報が漏洩したが、パスワードはハッシュ化されているためわからない
leaked_users_table = {
'jamie': {
'username': 'jamie',
'role': 'subscriber',
'md5': '203ad5ffa1d7c650ad681fdff3965cd2'
},
'amanda': {
'username': 'amanda',
'role': 'administrator',
'md5': '315eb115d98fcbad39ffc5edebd669c9'
},
'chiaki': {
'username': 'chiaki',
'role': 'subscriber',
'md5': '941c76b34f8687e46af0d94c167d1403'
},
'viraj': {
'username': 'viraj',
'role': 'employee',
'md5': '319f4d26e3c536b5dd871bb2c52e3178'
},
}
import hashlib
# ハッシュ化の例
word = 'blueberry'
hashlib.md5(word.encode()).hexdigest()
# 「よく使われるパスワードリスト」をハッシュ化し、「ハッシュ化前:ハッシュ化後」のパスワードの対応表を作る
rainbow_table = {}
for n in nist_bad:
hash_word = hashlib.md5(n.encode()).hexdigest()
rainbow_table[hash_word] = n
# ハッシュ後の値をrainbow_tableから検索して、ハッシュ化前のパスワードを割り出している。
for user in leaked_users_table:
try:
print(rainbow_table[leaked_users_table[user]['md5']])
except KeyError:
print(False)
参照URL
Udacity
Discussion