Slide 1

Slide 1 text

DjangoCongress JP 2018 梅崎 裕利 (@bungoume) Password Hashing

Slide 2

Slide 2 text

2 自己紹介 ❏ 梅崎 裕利 (@bungoume)  最近 bungou.me ドメイン取りました ❏ 検索API (Elasticsearch, Django) ❏ OAuth認可 API基盤 (DRF, oauthlib) ❏ アクセスログ分析

Slide 3

Slide 3 text

3 ニュースから

Slide 4

Slide 4 text

米Yahooから30億人分のデータ流出 4 米Yahooで2013年8月に起きた アカウント情報窃取 ● 氏名 ● メールアドレス, 電話番号 ● 生年月日 ● ハッシュ化されたパスワード ● セキュリティー用の質問と答え などが漏えい 2016年9月の発表当初は 5億人以上 でしたが... https://www.nikkei.com/article/DGXMZO21867310U7A001C1EAF000/

Slide 5

Slide 5 text

Adobe社のサイトの不正アクセス 5 2013年10月 少なくとも3800万人のIDと 暗号化されたパスワードが漏えい →暗号化が適切ではなく、すぐに解 読されてリストが流出 https://haveibeenpwned.com/ https://blog.tokumaru.org/2013/11/adobe.html

Slide 6

Slide 6 text

最近でも 6 2016年には一年で約30億件の ユーザー情報とパスワードが流出 http://www.cxotoday.com/story/over-300-bn-passwords-will-be -prone-to-cyber-attacks-by-2020-report/

Slide 7

Slide 7 text

7 ● DBからパスワードが漏れた時点で個人情報も多分漏れてる ● パスワードが一番重要なケース ○ IDとパスワードしか取得していない ○ 名前、生年月日は公開情報なSNS ● パスワードを他サービスと使いまわしている人は多い ○ 二次被害に繋がる ● 対策しているのが当然と思われている パスワードってそんなに大事?

Slide 8

Slide 8 text

8 ● パスワードだけが守るべき対象ではないが... ○ ユーザーの権限を利用されてしまう ○ パスワードを漏らすと他のサービスにも迷惑を与える YahooやAdobeのような大手IT企業でも起きており、 他人事ではない 過去の事例を教訓を活かすことが重要 過去の事件を教訓に

Slide 9

Slide 9 text

パスワードの保存方法

Slide 10

Slide 10 text

10 ● パスワードハッシュとは ● パスワード長と解析速度 ● 各パスワードハッシュの紹介 ○ Djangoでのデータ内容 ○ Djangoにおける歴史 ● 計算時間の比較 ● ハッシュ解析 アジェンダ

Slide 11

Slide 11 text

11 パスワードハッシュ関数(鍵導出関数) 例: PBKDF2_sha256 ● pass: P@ssw0rd ● salt: FkxESIA1MrrH ● iterations: 36000 ● hash: pxQUTiLxiWlkkY+0r5p43LfAHlQIw1ongOFv6FjVc/g= data: pbkdf2_sha256$36000$FkxESIA1MrrH$pxQUTiLxiWlkkY+0r5p43LfAHlQIw1ongOFv6FjVc/g= パスワードハッシュ関数

Slide 12

Slide 12 text

12 ● 鍵の管理が不要で運用しやすい ● 管理者も知るべきではない ● 秘密鍵だけ守るのはとても難しい 暗号化じゃなくてハッシュの理由

Slide 13

Slide 13 text

13 ● 長いパスワードは利用者にとって手間 ● 種類が少なければ、ハッシュといえど総当りで復元可能 ○ →あえて計算に時間がかかるようにする必要がある 人間の思いつくパスワードは限定的

Slide 14

Slide 14 text

14 IPAのコンピュータウイルス・不正アクセスの届出状況 (2008年10月) https://www.ipa.go.jp/security/txt/2008/10outline.html によると、 > 解読には最大で約50年 > 3種類(62文字数)で8桁のパスワードを作成すればパスワードの強度は十分 ・・・では今は? よくあるパスワード長の根拠

Slide 15

Slide 15 text

15 数十万円の機材で、8文字パスワードのSHA2-hashは 1分で全部解析可能になっている(かも?) (※あくまで可能性の話) 2018年、解析にかかる時間

Slide 16

Slide 16 text

16 1000万倍になると、「解析に1000年かかる」と言われていたもの が1時間未満に →パスワードの文脈だと困る 早くなりすぎでは!? 10年で1000万倍

Slide 17

Slide 17 text

17 SHA-256の計算はbitcoin採掘に 必要なため、超高速なハードウェア (ASIC)が開発が急速に進んだ ≒お金が流れ込んできた (bitcoin採掘ASICは直接パスワード解析には使えないので、あく まで理論値)ですが、パスワード分析できれば儲かるという話が 出ると同様になる可能性がある なぜか

Slide 18

Slide 18 text

18 2008年ごろ CPUでhash計算するのが主流。2M hash/sぐらい? 2010年ごろ GPUを利用したhash計算。 SHA1で1.3G hash/sぐらい? (約1000倍) 2014年ごろ bitcoinによりASIC開発が進む SHA256で14T hash/s (CPU比1000万倍) 時系列イメージ(主観)

Slide 19

Slide 19 text

19 ● 計算に時間の掛かるパスワードハッシュ関数を利用 ● ハードウェア化を行いにくくする ● (パスワード解析で得られる利益を減らす) どうすればよいの

Slide 20

Slide 20 text

20 各ハッシュアルゴリズムの概要

Slide 21

Slide 21 text

Django標準で使えるハッシュ関数 21 PASSWORD_HASHERS

Slide 22

Slide 22 text

22 ● auth_userのpassword field(char 128)に格納 ● $区切り ● 先頭はハッシュ方式 ● その後、パラメータとハッシュ(詳細は各関数に異なる) 例: pbkdf2_sha256$360000$dNhx87pKlB9E$xKRyAEunJkChipe BHaIbSNipBUOSTvUcqMUFrvz9UEI= Djangoにおけるパスワードデータ

Slide 23

Slide 23 text

歴史 23 Django1.4 から設定でハッシュ関数が変えられるように v0.91の段階でpasswordデータは先頭がハッシュ方式 [algo]$[salt]$[hexdigest] なので、アルゴリズム変更が可能 https://www.djangoproject.com/weblog/2005/nov/20/passwordchange/

Slide 24

Slide 24 text

24 ● SHA1+salt ● PBKDF2-SHA256 ● bcrypt ● (scrypt) ● Argon2 紹介するパスワードハッシュ関数

Slide 25

Slide 25 text

SHA1+salt 25 ● Django初期(〜1.3)の形式 ● ユーザ毎に異なる文字列(salt)をつけることで 同じパスワードでもhashが変わる ● 非推奨 ○ まだデータが残っていれば移行方法を検討 sha1 $ salt $ hash

Slide 26

Slide 26 text

PBKDF2 26 ● Djangoのデフォルト方式で、よく利用される ● ライブラリ不要 ● iterationsを増やすのが容易 pbkdf2_sha256$360000$dNhx87pKlB9E$xKRyAEunJkChipeBHaIbSNipBUOSTvUcqMUFrvz9UEI= pbkdf2_sha256 $ iterations $ salt $ hash

Slide 27

Slide 27 text

27 イテレーション回数はバージョン更新ごとに増加 v1.4-1.6: 10000 ->v1.7: 12000 -> v1.8: 20000 -> v1.9: 24000 -> v1.10: 30000 -> v1.11: 36000 -> v2.0: 100000 -> v2.1: 120000 https://docs.djangoproject.com/en/dev/internals/howto-release-django/#new-stable-branch-tasks > New stable branch tasks Increase the default PBKDF2 iterations in > django.contrib.auth.hashers.PBKDF2PasswordHasher by about 20% PBKDF2のイテレーション数

Slide 28

Slide 28 text

sha2+bcrypt 28 ● Blowfishという古い暗号化方式を利用 ● ハードウェア化が難しいとされる ● iterationsで計算量を増やすことが可能 ○ 必要メモリ量の調整はできない ● BCryptPasswordHasherはパスワードを72文字で切り捨て ● PHPの標準方式 (Railsも?) ● Dropboxなど利用事例も多い bcrypt_sha256$$2b$12$EJOn/KeVwTB47B0dgUpG.u5vF/BKKQXrJ/GWPeKLHCSYMPZUgis9a

Slide 29

Slide 29 text

(scrypt) 29 ● Django標準では用意されていない ● 従来の方式に比べてメモリ使用量を増やし、ハードウェア化を難 しくしてある ● TMTO(Time-Memory Trade Off)=計算量を増やす代わりに メモリ使用量を削減することができてしまう ● bitcoinフォークのLitecoinで利用されているらしく、既にある程度 ハードウェア化されている

Slide 30

Slide 30 text

Argon2 30 ● Password Hashing Competition(2015.7) 勝者 ● Djangoで利用にはサードパーティのライブラリが必要 ● メモリ使用量を設定するパラメータがある ○ django m=512(kB), t=2(iterations), p=2(threads) ○ PHP7.2 m=1024, t=2, p=2 ○ Argon2 cli m=4096, t=3, p=1 argon2$argon2i$v=19$m=512,t=2,p=2$UUs1czNhenF3ZGs3 $LPSAw5kqjDMtvKq8M+A6Jw

Slide 31

Slide 31 text

Argon2 31 ● argon2i サイドチャネル攻撃耐性 ● argon2d GPUを使った攻撃に対する耐性 ● argon2id いいとこ取り argon2iがパスワードに適している(PHP7.2もargon2iを利用) argon2idはできて日が浅い

Slide 32

Slide 32 text

速度比較 32 設定値 100回 (秒) 1回あたり SHA1+Salt 0.0074 0.01 ms PBKDF2 iterations = 100000 12.6987 127 ms SHA2+bcrypt rounds = 12 38.6854 387 ms Argon2 m=512, t=2, p=2 0.1901 2 ms ## python version: 3.6.5 ## python compiler: GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1) ## cpu model: Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz

Slide 33

Slide 33 text

33 ● 古いハッシュ形式・iterationsが少ないユーザー ○ Djangoはログインのタイミングで自動的に強化 ○ ログイン試行するだけでiterations数が増える関数も ● 最近アクセスしていない人は変更されない ■ 長く続いているサービスはバッチで置き換えをする ハッシュ関数を変えた後は

Slide 34

Slide 34 text

django内でのhash関数 34 変数 algorithm, iterations, など 関数 encode, verify, safe_summary, must_udpate, harden_runtime

Slide 35

Slide 35 text

パスワードハッシュが弱いと 35 防げたはずの問題だったとして 取り上げられたケースも https://www.wired.com/story/under-armour-myfitnesspal-hack- password-hashing/

Slide 36

Slide 36 text

Password Recovery 36

Slide 37

Slide 37 text

Password Recovery 37 パスワードを忘れてしまったとき Hashから元の文字列を実際に復元するには

Slide 38

Slide 38 text

hashcat 38 ● 世界最速を謳うパスワードクラッカー ● https://hashcat.net/hashcat/ ● OSS (MIT) ● GPU, FPGAなど利用可能 ● 200以上のhashに対応 ○ Django (SHA-1) ○ Django (PBKDF2-SHA256) 注: パスワードクラックを推奨するものではありません。

Slide 39

Slide 39 text

使い方 39 $ sqlite3 db.sqlite3 "SELECT password FROM auth_user;" > django_pass.txt $ hashcat -m 10000 -a 0 django_pass.txt 10-million-password-list-top-10000.txt -O

Slide 40

Slide 40 text

パスワードリスト 40 ● https://github.com/danielmiessler/SecLists ● セキュリティ評価のためのユーザ名, パスワードなど

Slide 41

Slide 41 text

デモ 41

Slide 42

Slide 42 text

デモ結果 42 ● パスワードリストに載ると一瞬 ○ パスワードハッシュ関数を選んでも、辞書攻撃には弱い ● 利用者には強いパスワードを利用してもらうのが大事 ○ リストに乗ったものは利用させない

Slide 43

Slide 43 text

43 リストから消せばよい?

Slide 44

Slide 44 text

44 そのほか

Slide 45

Slide 45 text

45 オフライン攻撃が容易な箇所は注意が必要 ● 秘密鍵 ○ v2のsshkeyやed25519はKDFラウンド数指定可能(-a) ● zip ○ stretchなし or hmac-sha1×1000ラウンド ● Word, Excel ○ 2007以降は50000〜100000ラウンド DBだけでなくファイルも注意 参考 https://www.slideshare.net/herumi/ss-57319518#4

Slide 46

Slide 46 text

パスワードハッシュで出来なくなること 46 ● チャレンジレスポンス型認証 ○ CHAP ○ CRAM-MD5 ○ DIGEST-MD5 ● クライアントでワンタイムnonceを使ってハッシュを計算 ○ サーバー側でも生passwordが必要

Slide 47

Slide 47 text

47 まとめ

Slide 48

Slide 48 text

まとめ 48 ● Djangoは標準のパスワードハッシュでも問題はない ○ Argon2を選ぶともっと良い ○ Djangoのパスワードハッシュアルゴリズムの変更は容易 ● 利用者は強いパスワードを使うこと ● 昔から動かしているサービスはハッシュ移行を検討 ● Password management in Django に詳細