しまたろさんの掃き溜め

メモ帳みたいなもの

メールアドレスをハッシュ化したものを公開してもよいのか

注意

この記事は攻撃の実行を教唆する目的で書かれたものではなく、特定の状況におけるセキュリティ上の問題点を指摘するために公開しているものです。この記事に書かれた内容を実行して発生した結果について、筆者は一切の責任を負いません。

はじめに

インターネット上で他人のメールアドレスをmd5で二重ハッシュしたものを公開されている方を見かけたため、解析する実験を行いました。

メールアドレスのユーザー名部分は多くの場合小文字のアルファベットと数字のみ(36文字)のそれほど長くない列で構成されており、ブルートフォース攻撃(総当り攻撃)によって簡単に特定できてしまうと考えられます。

またドメイン部分に関しても、一般の方が使うメールプロバイダが限られていることを考慮すると、サイズの小さい辞書でも十分な確率で当たるものと考えられます。

実験

今回はhashcatという、GPUハッシュ値を解読するソフトウェアを用いました。

用いたコンピューターは以下のもので、確か8万とかで組んだやつなので十分一般のご家庭にあるコンピューターの範疇だと思います。

解読する対象として、example@example.commd5sumコマンドに2度掛けて生成された以下の文字列をhash.txtとして保存しておきます。

9e7bfa73e24be13c18e592d7dedbe793

また、今回はドメイン名が以下の2つのいずれかであることがわかっている状況であると想定し、以下のように辞書ファイルdomain.dictを作成します。

@example.com
@example.jp

この状態で以下のコマンドを実行すると解析が始まります。

./hashcat64.bin -m 2600 -a 7 -i hash.txt -1 '?l?d' '?1?1?1?1?1?1?1' domain.dict

各オプションの意味を説明しますが、詳細はhashcat wikiをご参照ください。

  • -m 2600 ハッシュ関数の種類を番号で指定しています。2600はmd5(md5(pass))に当たります。
  • -a 7 モードの指定です。今回はブルートフォースと辞書型のハイブリット(前半のユーザー名部分がブルートフォース、後半のドメイン部分が辞書型)を指定しています。
  • -1 '?l?d' これを記述しておくことで、この後のマスクパターンで?1がアルファベット小文字と数字の中からどれか1文字、を表すようになります。
  • '?1?1?1?1?1?1?1' ドメイン名部分で総当りするパターンの指定(マスクパターン)です。今回は英小文字数字の7文字(以下)の列を総当りで解析するように指定しています。

結果

出力の一部抜粋です。

9e7bfa73e24be13c18e592d7dedbe793:example@example.com

Session..........: hashcat
Status...........: Cracked
Hash.Type........: md5(md5($pass))
Hash.Target......: 9e7bfa73e24be13c18e592d7dedbe793
Time.Started.....: Mon Jun  1 22:01:48 2020 (54 secs)
Time.Estimated...: Mon Jun  1 22:02:42 2020 (0 secs)
Guess.Base.......: File (domain.dict), Right Side
Guess.Mod........: Mask (?1?1?1?1?1?1?1) [7], Left Side
Guess.Charset....: -1 ?l?d, -2 Undefined, -3 Undefined, -4 Undefined
Speed.#1.........:   103.0 MH/s (8.73ms) @ Accel:1024 Loops:2 Thr:256 Vec:1
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 5580521472/156728328192 (3.56%)
Rejected.........: 0/5580521472 (0.00%)
Restore.Point....: 2788687872/78364164096 (3.56%)
Restore.Sub.#1...: Salt:0 Amplifier:0-2 Iteration:0-2
Candidates.#1....: snlsww1@example.com -> 9zv29al@example.jp
Hardware.Mon.#1..: Temp: 50c Fan: 32% Util: 98% Core:1746MHz Mem:3504MHz Bus:16

Started: Mon Jun  1 22:01:00 2020
Stopped: Mon Jun  1 22:02:43 2020

ということで、今回は合計1分43秒でハッシュ値からexample@example.comを当てることができました。

注目するべきはSpeedの行で、今回1秒間で100M個(1億個)のメールアドレスに当たることができました。ここから、例えばユーザー名が英小文字と数字の中から9文字で、ドメインがもともとわかっているようなメールアドレスを解析するには、369/100000000 = 1015599秒、すなわち約11日あればご家庭のコンピューターでも十分に解析できると考えられます。(これは最後の最後まで当たらなかった運の悪い場合なので、実際にはもう少し早く見つかることが期待される)

もちろんクラウドの計算資源を借りるなどすれば、もっと早く計算できる、もしくはこれより1,2文字長いようなメールアドレスの解析も現実的でしょう。

結論

  • ハッシュだからといってむやみに公開してはいけない
  • パスワードには大文字記号も使おう
  • saltとかちゃんとかけよう
  • md5に掛けた他人のメールアドレスをインターネット上で公開している方は速やかに消すことをおすすめします。

追記

今回の実験では、そもそも既にハッシュ関数としては脆弱であるmd5を用いました。これは、この記事を書くきっかけになった「インターネット上で見かけたメールアドレス」がmd5(md5(m))でハッシュ化されていたためです。

しかし、今回の実験はmd5自体の脆弱性とは関係なく、任意のハッシュ関数で同様の攻撃が成り立つことを補足しておきます。(もちろん関数によってハッシュ化にかかる時間が違うのでその分総所要時間は変わりうるが…)

実際、バリバリ現役のハッシュ関数であるSHA-256(二重ではない)で同様の実験をしたところ、1分34秒で結果が出ています。

ハッシュ関数が何であっても、元データがある程度推測可能なもののハッシュを公開してはいけません。