Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
djangocongressjp2023_password_hash
Search
bungoume
October 06, 2023
Programming
1.6k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
djangocongressjp2023_password_hash
bungoume
October 06, 2023
More Decks by bungoume
See All by bungoume
日経電子版でのDjango活用事例紹介 / djangocongressjp2022-nikkei
bungoume
4
7.2k
CircleCIの活用事例とCI高速化/circleci-community-meetup3-speedup
bungoume
3
1.6k
Password Hashing djangocongress 20180519
bungoume
5
4.2k
OSSで始めるセキュリティログ収集/oss-securitylog-builderscon2017
bungoume
29
11k
日経電子版のアプリ開発を支えるログ活用術/nikkei-log-201609
bungoume
1
1.4k
Kibanaで秒間1万件のアクセスを可視化した話/nikkei-kibana-loganalyst2015
bungoume
20
17k
uwsgi-docker-pycon2015
bungoume
10
61k
Ansibleを結構使ってみた/ansible-nikkei-2015
bungoume
32
15k
Dynamic Inventoryと参照変数
bungoume
2
5.1k
Other Decks in Programming
See All in Programming
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
360
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
160
引き算の組織 ― アウトカムとAIに全振りするために辞めたこと ― / Organization by Subtraction
hirokiyamamoto14
PRO
0
290
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
450
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
120
運用ダッシュボードの設計を誰も教えてくれないのだけどみなさんどうしてるんですか? - チームに監視するという文化を根付かせるための第一歩を踏みたい -
satoshi256kbyte
1
140
Gmail/Google DriveをトリガーにAIエージェントを動かそう! / Run AI agents with Gmail/Google Drive as triggers!
har1101
2
430
Discordを用いたラボオートメーション関連情報収集の自動化
noguhiro2002
0
400
170k Jobs a Day on GKE: Scaling Mercari's CI Platform - and What's Next for AI-Native Development
junyaokabe
0
120
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
2
120
初めての模倣学習とVLA
natsutan
0
210
typoなんかねぇよ
raspython3
0
490
Featured
See All Featured
KATA
mclloyd
PRO
35
15k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
490
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
500
We Have a Design System, Now What?
morganepeng
55
8.3k
The Language of Interfaces
destraynor
162
27k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
260
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
210
Facilitating Awesome Meetings
lara
57
7.1k
For a Future-Friendly Web
brad_frost
183
10k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
300
Transcript
DjangoCongress JP 2023 梅崎 裕利 (@bungoume) Djangoのパスワードハッシュ
2 自己紹介 ❏ Yuri Umezaki (@bungoume) ❏ 検索API (Elasticsearch, Django)
❏ OAuth認可 API基盤 ❏ アクセスログ分析
自分のパスワードが流出しているか確認 3 HaveIBeenPwned.com https://haveibeenpwned.com/
4 • パスワードだけが守るべき対象ではないが... ◦ ユーザーの権限を利用されてしまう ◦ パスワード漏えいは他のサービスにも影響を与える 大手IT企業でも起きており、他人事ではない 過去の事例を教訓に活かすことが重要 過去の事件を教訓に
パスワードの保存方法
6 • パスワードハッシュとは • パスワード長と解析速度 • 各パスワードハッシュの紹介 ◦ Djangoでのデータ内容 ◦
Djangoにおける歴史 • 計算時間の比較 • ハッシュ解析 アジェンダ
7 • ハッシュ化とは、辞書において "細かく刻む、切り刻む、細切れにする" • ハッシュ値はデータを固定長の値に変換したもの ◦ 同じ値からは同じハッシュが作られる • パスワード文脈では
◦ 漏洩後にパスワード悪用をできるだけ遅らせたい パスワードのハッシュとは
8 • 両方とも、機密データを安全に保つ方法 パスワードは暗号化ではなくハッシュ化する必要がある (ほぼすべてのケースでハッシュ化が必要) ハッシュと暗号化
9 • ハッシュは一方向関数 ◦ 復号して平文を取得することはできない ◦ ハッシュを取得してもそのままログインには使えない ◦ (取得はできないが解読はできる。後述) •
暗号化は双方向 ◦ 元の平文を取得可能 ハッシュと暗号化
10 • 長いパスワードは利用者にとって手間 • 種類が少なければ、ハッシュといえど総当りで復元可能 ◦ →あえて計算に時間がかかるようにする必要がある 人間の思いつくパスワードは限定的
11 IPAのコンピュータウイルス・不正アクセスの届出状況 (2008年10月) https://www.jacic.or.jp/topics/2008100201/ipa_200809.pdf によると、 > 解読には最大で約50年 > 3種類(62文字数)で8桁のパスワードを作成すればパスワードの強度は十分 ・・・では今は?
よくあるパスワード長の根拠
12 オフライン攻撃想定 MD5をGeForce RTX2080 (40GH/sec)で計算した場合の時間 8桁の英大小文字+数字で1時間 • 2023最新のRTX 4090は150GH/secなので更に約¼ ◦
9桁の英大小文字+数字が約1日 2020 パスワード総当り 必要時間表 https://www.response-it.co.uk/news/2020/9/2/how-long-does-it-take-to-crack-your- password https://openbenchmarking.org/test/pts/hashcat
13 2008年に比べてCPU性能は向上。 GPUによる計算も広まり、10万倍近くのハッシュ計算性能が簡単 に出せるように。 また、暗号通貨系で広まったASIC等がパスワード解析に利用さ れると更に大幅に高速となる可能性もある 計算性能向上・GPGPU、ハードウェア化
14 利用者 • パスワードは使い回さない/長いパスワード • パスワードマネージャを使うのも手 システム側 • 計算に時間の掛かるパスワードハッシュ関数を利用 •
ハードウェア化を行いにくくする • (世の中的に正しいとされる設定を使う) どうすればよいの
15 各ハッシュアルゴリズムの概要
16 現時点でのセキュリティ上 ベストな設定が色々掲載 https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html OWASP Cheat Sheet
Django4.1まで 使えたハッシュ関数 17 PASSWORD_HASHERS
Django4.2 標準で使えるハッシュ関数 18 PASSWORD_HASHERS
19 • Argon2 • pip install argon2-cffi • settings.py に以下の設定を入れればOK
◦ (先頭のものが利用されます。2つ目以降は移行用) おすすめの設定
20 ソルト • 各パスワードに追加される、ランダムな一意の文字列 • パスワードごとに別の値 目的 • レインボーテーブル(事前計算されたハッシュDB)を使った解読 の保護
• 大量ハッシュの同時解読難化 • パスワードが同じ人の特定を防ぐ 用語: ソルト(salt)
21 ソルトのイメージ
22 • ソルトに加えて利用するシステム共通の文字列 • データベース以外に保存 目的 • DBのデータのみが流出した際の解読リスクを減らす 用語: ペッパー(Pepper)
23 • 計算コストを増やす目的 • 何度も繰り返しハッシュ化し元データ推測を困難にする • 数十万回行うことも • ストレッチ回数: iterations
用語: ストレッチング mypassword 91dfd9dd… fabe5482… 83d5743b… ハッシュ化 ハッシュ化 ハッシュ化
24 よく使われるのは Modular crypt format (MCF) $6$SALT$bWoY9tMqAn7I9eJU/mmCZoOL6wokwfHgWBWRvbDrUMpmMpNk /zyQaJe70FiLSvJyzi9lB6GtoivF1/NMwymZa1 Linuxの/etc/shadowなど https://passlib.readthedocs.io/en/stable/modular_crypt_format.html
ハッシュ化したパスワードの保存形式
25 • auth_userのpassword field(char 128)に格納 • $区切り • 先頭はハッシュ方式 •
その後、パラメータとハッシュ(詳細は各関数に異なる) 例: [タイプ]$[ストレッチ回数]$[ソルト]$[ハッシュ] Djangoにおけるパスワードデータ pbkdf2_sha256$360000$dNhx87pKlB9E$xKRyAEunJkChipeBH aIbSNipBUOSTvUcqMUFrvz9UEI=
歴史 26 Django1.4 から設定でハッシュ関数が変えられるように v0.91の段階でpasswordデータは先頭がハッシュ方式 [タイプ]$[salt]$[hexdigest] なので、アルゴリズム変更が可能 https://www.djangoproject.com/weblog/2005/nov/20/passwordchange/
27 • PBKDF2 • bcrypt • scrypt • Argon2 紹介するパスワードハッシュ関数
PBKDF2 28 • Djangoのデフォルト方式で、よく利用される • ライブラリ不要 • iterationsを増やすのが容易 • NIST
FIPS-140 で推奨 [タイプ]$[ストレッチ回数]$[ソルト]$[ハッシュ] pbkdf2_sha256$720000$FkxESIA1MrrH$EXYJuJLVXjJ8A+MLGKJ9bfQ2HWr1mRhcB2tlSHyWiG4=
29 イテレーション回数はバージョン更新ごとに増加 v1.4-1.6: 10000 ->v1.7: 12000 … -> v2.0: 100000
-> v2.1: 120000 … -> v4.2 600000 -> v5.0 720000 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のイテレーション数
SHA256+bcrypt 30 • Blowfishという古い暗号化方式を利用 • ハードウェア化が難しいとされる • iterationsで計算量を増やすことが可能 ◦ 必要メモリ量の調整はできない
• BCryptPasswordHasherはパスワードを72文字で切り捨て • PHPなどの標準方式 • 利用事例も多い [タイプ]$[タイプ]$[ストレッチ回数]$[ソルト(22文字)][ハッシュ(31文字)] bcrypt_sha256$$2b$12$XScV8pd5i/ERqlLx2Q1Ipu2qBGUlc1HorN5Y4mEOurNlt/K6/UC.u
scrypt 31 • Django4.0から利用可能 • メモリ使用量を増やし、ハードウェア化を難しくした設計 • bitcoinフォークのLitecoinで利用されているらしく、既にある程度 ハードウェア化されている ◦
TMTO(Time-Memory Trade Off)等でハードウェア化を防ぎきれなかった ◦ 選択肢として致命的な問題があるわけではなさそう [タイプ]$[メモリ,CPUコスト]$[ソルト]$[ブロックサイズ]$[並列数]$[ハッシュ] scrypt$16384$AHnJwIHTDWiUrcEelaZ3i6$8$1$upF27cH+BRCe8QFnTNkby7eN3RuDw/GJslociOjopz PIZM4ebz2GPnHLBtZl6ZhRR28p54pL8cm5mPcvBSodcg==
Argon2 32 • Password Hashing Competition(2015.7) 勝者 • メモリ使用量を設定するパラメータがある •
Djangoで利用にはサードパーティのライブラリが必要 ◦ pip install argon2-cffi [タイプ]$[タイプ]$[バージョン]$[m=メモリコスト],[t=タイムコスト],[p=並列数]$[ソルト]$[ハッシュ] argon2$argon2id$v=19$m=102400,t=2,p=8$S0JrY1YzVDYwTjg0dlE1UjRvUTllSA$bDLYCv6H6wZ mu6ZWjEby0twmI27SApnFEyjyrszNJ9E
Argon2 33 • argon2i サイドチャネル攻撃耐性 • argon2d GPUを使った攻撃に対する耐性 • argon2id
いいとこ取り 今はargon2idが推奨 Djangoは3.2よりargon2iからargon2idに変更 (PHPは7.2でargon2iを導入、PHP7.3でargon2idをサポート)
速度比較 34 設定値 1回あたり Mem PBKDF2 iterations = 720000 (v5.0
default) 390 ms 0.0 MiB SHA256+bcrypt rounds = 12 (default) 250 ms 0.2 MiB scrypt N=2^14(16 MiB), r=8, p=1 (default) 47ms 16.0 MiB scrypt N=2^14(16 MiB), r=8, p=5 (OWASP) 220ms 16.0 MiB Argon2id t=2, m=102400, p=8 (default) 56 ms 100.4 MiB Argon2id t=2, m=19456, p=1 (OWASP) 33ms 19.0 MiB ## python version: 3.11.4 ## python compiler: Clang 14.0.0 (clang-1400.0.29.202) ## cpu model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
速度比較(2018の資料, CPUが違います) 35 設定値 100回 (秒) 1回あたり SHA1+Salt 0.0074 0.01
ms PBKDF2 iterations = 100000 12.6987 127 ms SHA256+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
36 1. Argon2id 2. Argon2idが使用できない場合はscrypt 3. 今使ってる場合はbcrypt 4. FIPS-140 準拠が必要な場合PBKDF2
それぞれ安全な設定値で使うこと (+多層防御としてペッパーの追加を検討) OWASPの推奨値
37 • 古いハッシュ形式・iterationsが少ないユーザーデータ ◦ Djangoはログインのタイミングで自動的に強化 ◦ スムーズに移行が可能 • 最近アクセスしていない人は変更されない ▪
長く続いているサービスはバッチで置き換えをする ハッシュ関数を変えた後は
django内でのhash関数 38 変数 algorithm, iterations, など 関数 encode, verify, safe_summary,
must_udpate, harden_runtime
Password Recovery 39
Password Recovery 40 パスワードを忘れてしまったとき Hashから元の文字列を実際に復元するには
hashcat 41 • 世界最速を謳うパスワードクラッカー • https://hashcat.net/hashcat/ • OSS (MIT) •
GPU, FPGAなど利用可能 • 200以上のhashに対応 ◦ Django (SHA-1) ◦ Django (PBKDF2-SHA256) 注: パスワードクラックを推奨するものではありません。
使い方 42 $ 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
パスワードリスト 43 • https://github.com/danielmiessler/SecLists • セキュリティ評価のためのユーザ名, パスワードなど
デモ 44
45
デモ結果 46 • パスワードリストに載ると一瞬 ◦ パスワードハッシュ関数を選んでも、辞書攻撃には弱い • 利用者には強いパスワードを利用してもらうのが大事 ◦ リストに乗ったものは利用させない
◦ CommonPasswordValidatorですこしはチェックできる
47 そのほか
48 オフライン攻撃が容易な箇所は注意が必要 • 秘密鍵 ◦ 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
パスワードハッシュで出来なくなること 49 • チャレンジレスポンス型認証 ◦ CHAP ◦ CRAM-MD5 ◦ DIGEST-MD5
• クライアントでワンタイムnonceを使ってハッシュを計算 ◦ サーバー側でも生passwordが必要
50 まとめ
まとめ 51 • DjangoのパスワードハッシュはArgon2を選ぶと良い ◦ 標準の設定(PBKDF2)でも全く問題はない ◦ Djangoのパスワードハッシュアルゴリズムの変更は容易 • パスワードハッシュ計算は以前より時間がかかる
◦ API用などで都度検証する実装の場合、性能劣化要因になっている可能性 • 利用者は強いパスワードを使うこと • 昔から動かしているサービスはハッシュ移行を検討 • Password management in Django に詳細