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
7k
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
60k
Ansibleを結構使ってみた/ansible-nikkei-2015
bungoume
32
15k
Dynamic Inventoryと参照変数
bungoume
2
5.1k
Other Decks in Programming
See All in Programming
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
120
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
さぁV100、メモリをお食べ・・・
nilpe
0
140
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
5.1k
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
6.7k
Go1.27で導入されるジェネリクスメソッドでできること
mackee
0
120
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
120
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
Oxlintのカスタムルールの現況
syumai
6
1.1k
Spec Driven Development | AI Summit Lisbon
danielsogl
PRO
0
190
dRuby over BLE
makicamel
2
340
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
170
Featured
See All Featured
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
200
Accessibility Awareness
sabderemane
1
140
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
210
From π to Pie charts
rasagy
0
210
Documentation Writing (for coders)
carmenintech
77
5.4k
The untapped power of vector embeddings
frankvandijk
2
1.8k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
Ruling the World: When Life Gets Gamed
codingconduct
0
250
Practical Orchestrator
shlominoach
191
11k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
Everyday Curiosity
cassininazir
0
230
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 に詳細