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
Webアプリケーションにおけるパスワードの管理について
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
mrtc0
September 12, 2016
Programming
10k
28
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Webアプリケーションにおけるパスワードの管理について
#LT駆動 29での発表スライド
mrtc0
September 12, 2016
More Decks by mrtc0
See All by mrtc0
Datadog を使ったプロダクトとクラウドの セキュリティモニタリング
mrtc0
0
3.4k
コードで理解する eBPF セキュリティモニタリング
mrtc0
2
310
Product Security Casual Talk #1 - Datadog を使ったセキュリティモニタリングと 自動化の取り組み
mrtc0
2
720
GMO ペパボ株式会社 23卒・24卒向け セキュリティ勉強会 実践 DevSecOps パイプライン
mrtc0
1
750
実践 DevSecOps パイプライン ~システム開発へのセキュリティの取り入れ方~
mrtc0
2
610
脅威モデリングで考える Kubernetes セキュリティ / CloudNative Days Tokyo 2021 #CNDT2021 #CNDT2021_B
mrtc0
8
3.5k
ProSec-IT 2021 Container Security
mrtc0
2
830
GMO Developer Day 2021 - DevSecOps 推進の取り組みの紹介.pdf
mrtc0
4
1.8k
Web セキュリティ研修 / GMO ペパボ 新卒研修 2021
mrtc0
7
46k
Other Decks in Programming
See All in Programming
タクシーアプリ『GO』の バックエンド開発のおける AI利活用と若者のすべて
pyama86
3
2k
AutonomyとControlのあいだ:Graflowで記述するAIエージェント協調
myui
0
120
A2UI という光を覗いてみる
satohjohn
1
130
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
AI時代のUIはどこへ行く?その2!
yusukebe
21
7k
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.3k
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
260
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
110
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
210
Contextとはなにか
chiroruxx
1
290
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
250
OSもどきOS
arkw
0
530
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
610
Tell your own story through comics
letsgokoyo
1
950
Git: the NoSQL Database
bkeepers
PRO
432
67k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
Designing Powerful Visuals for Engaging Learning
tmiket
1
410
sira's awesome portfolio website redesign presentation
elsirapls
0
280
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
390
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
330
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
Statistics for Hackers
jakevdp
799
230k
Transcript
Webアプリケーションにおける パスワードの管理について 2016-09–04 LT駆動開発 #29 @mrtc0
> whoami • もりたこ(@mrtc0) • ChainerでXSS検知するやつ作った – https://mrtc0.com/lab/php/index.php?q=hello
背景 • パスワードをDBに保存するときに、具体的に どう保存すればいいのか – ハッシュ化 + ソルト – 使用するアルゴリズムはどれにすべきか?
– ちゃんと整理したい • 昨日の深夜にサクッと作ったので気軽にマサカ リ投げてください • Djangoでどういった実装がされているのか
Case 1 • パスワードを平文のまま保存 +------+--------+------------+ | id | name |
password | |------+--------+------------| | 1 | admin | password | +------+--------+------------+
平文での保存 • 推奨されない(当たり前) • 第三者が容易にログインできる • 他人のパスワードの生成パターンを予測できる – Aさんは 文字列+誕生日
とか
Case2 • DB内でパスワードを暗号化 +------+--------+------------------+ | id | name | password
| |------+--------+------------------| | 1 | admin | 402fda0cde783273 | +------+--------+------------------+
暗号化して保存 • Ad be ◦ が過去に採用していたケース • 暗号化されて安全だね!やったー! – とはならない
• 暗号化するプログラムが入手されたら? • 同じパスワードからは同じ文字列が生成される
Case3 • パスワードをハッシュ化して保存 +------+--------+----------------------------------+ | id | name | password
| |------+--------+----------------------------------| | 1 | admin | 5f4dcc3b5aa765d61d8327deb882cf99 | +------+--------+----------------------------------+
ハッシュ化して保存 • 一方向ハッシュ関数を使用して保存 – パスワードの長さに関する情報はなくなった – ユーザーにパスワード長を制限する必要もない – 可逆性がなくなった •
しかし...!
ハッシュ化して保存 • 単にハッシュ化して保存するだけではダメ – 同じパスワードからは同じハッシュ値が生成される • レインボーテーブルを使用したクラック – 事前にパスワード:ハッシュ値のデータを容易して おく(レインボーテーブル)
余談 • MD5 Collision – http://www.mscs.dal.ca/~selinger/md5collisio n/ – 異なるファイルでもMD5ハッシュ値が同じ •
SHA1でもMD5ほどではないが、衝突の危険性 がある
パスワード保存の要件 • DBパスワードを保存する際には以下の要件を 必ず満たす必要がある – 管理者でもユーザーのパスワードを復元できない – 同一パスワードから同一ハッシュ値を生成しない – 十分にストレッチングを行う
Case4 • ハッシュ + ソルトを使用 +------+--------+--------------------------------+ | id | name
| password | |------+--------+--------------------------------| | 1 | admin | $1$salt$qJH7.N4xYta3aEG/dfqo/0 | +------+--------+--------------------------------+
ハッシュ+ソルト • 16byte以上のソルトを使用すること • ランダムなソルトを使用 – random()は使わない – CryptAPIとか/dev/urandomとか •
これで同じパスワードから同じハッシュ値が生 成される問題はなくなった • だいぶ堅牢になったぞ!!!!!
ストレッチング • ハッシュ + ソルトな方式を使用することで かなり堅牢になった • しかし、まだだ!!! • 最新GPUを大量に積めば一瞬で大量のSHA-
256 Hashを計算することも可能 – 最近ではAWSに金をつぎ込むことでも可能! • 現実的に計算できないようにするためにスト レッチングを行う
ストレッチング • ハッシュの計算を何回も繰り返す • PBKDF2, bcryptなどの使用が推奨 – 独自で実装をしてはいけない – 確かNISTが資料を出していたはず(要出典)
PBKDF2 • KDF(Key Derivation Function) – 鍵導出関数 – 固定長で一定のエントロピーを持つより安全な鍵を 得ることが可能
– パラメータに繰り返し回数があり、計算量を調整で きる • PBKDF2はRFC2898に基づたKDF
PBKDF2 • DK = PBKDF2(PRF, Password, Salt, c, dkLen) –
PRF : 疑似乱数生成関数. HMAC – Password : パスワード – Salt : ソルト – C : 繰り返す回数 – DkLen : 出力する導出鍵の長さ
HMAC • MAC(Message Authentication Code)の1つ – 共通鍵を用いて固定長のメッセージを出力する – 改竄検知に使用
MD(Message Digest) • 所謂、一方向ハッシュ関数 – 任意のメッセージから固定長メッセージを生成 – admin → 5f4dcc3b5aa765d61d8327deb882cf99
• 異なるメッセージから同一のハッシュ値を生成 することが困難でなければいけない • ちなみにCRC32のような誤り検出符号は暗号 的ハッシュ関数とは区別される
MDとMAC • MD ... メッセージを容易に計算できる • MAC … 共通鍵がなければ計算できない •
共通鍵なので否認を防止することができない • つまり、メッセージを生成したものが本人であ るという保証はされない
HMAC • ハッシュ関数 + MAC • すべてのハッシュ関数に適用可能 – それぞれHMAC-MD5とかHMAC-SHA1とか •
他にもCBC-MACなどもある – ブロック暗号アルゴリズムと組み合わせる方式 – OMAC/CMAC, PMAC
PBKDF2 • DK = PBKDF2(PRF, Password, Salt, c, dkLen) –
PRF : 疑似乱数生成関数. HMAC – Password : パスワード – Salt : ソルト – C : 繰り返す回数 – DkLen : 出力する導出鍵の長さ • で、何回繰り返せばいい???
Djangoの実装を見てみる • Djangoでは標準で、ユーザーのパスワードを PBKDF2で保存している from django.contrib.auth.models import User user =
User(username="user") user.set_password('password') user.password 'pbkdf2_sha256$24000$NPCTHzvjHgPo$phHqNmNOafrNsxYXZm2HNpPBXzqBVijvakAFVkR HbZs='
Djangoでの実装 user.password.split('$') ['pbkdf2_sha256', '24000', 'NPCTHzvjHgPo', # salt 'phHqNmNOafrNsxYXZm2HNpPBXzqBVijvakAFVkRHbZs='] • PBKDF2
+ HMAC + SHA256で24000回繰り返している
ちなみに • 最新Ver(1.10)では24000回だったが... • マシンの性能の向上に伴って計算回数も増えて いっている Ver 回数 1.9 2015.12
24000 1.8 2015.01 20000 1.7 2014.02 15000 1.6 2013.06 12000 1.5 2013.02 10000
計算速度の問題 • 結構な回数を計算していることがわかったが... • 非常に長いパスワードを計算すると、かなり時 間がかかるのでは?
計測してみた • i5-2520M 2.50GHz – 64文字と10000000文字(10MB)で試す from timeit import timeit
setup = ''' from django.contrib.auth.hashers import PBKDF2PasswordHasher hasher = PBKDF2PasswordHasher() password = "A" * 10000000 salt = "salt" ''' result = timeit(stmt = 'hasher.encode(password = password, salt = salt, iterations = 24000)', setup=setup, number=500) print(result)
計測してみた • 64文字のとき…11.665050101000816 • 10MBのとき… 32.772370806000254 • という感じなので、Djangoでは4098文字制限 がある –
https://www.djangoproject.com/weblog/2013/ sep/15/security/
まとめ • パスワードを保存する際には以下の要件を必ず満たす 必要がある – 管理者でもユーザーのパスワードを復元できない – 同一パスワードから同一ハッシュ値を生成しない • 具体的には
– 疑似乱数発生関数である程度の長さのソルトを使ってハッ シュ値を生成する – KDFで十分な回数繰り返す • WAFでは標準で実装されていたり、ライブラリも充実 しているので積極的に頼っていくべき
感想と疑問 • マシンの性能を考えてストレッチングの回数を 増減したほうが良さそう • マシンやGPUの性能向上に伴って使用するアル ゴリズムやストレッチングの回数を変更してい なければならない • 変更するときにどうすればいいのか
– ログイン時に再生成? – 緊急のときはアカウント停止?