PHP7.0世代のハッシュ、暗号化、暗号論的乱数生成およびCSRF対策周りのメモ
独自フレームワークのPHP7対応に絡んで、認証 および CSRF対策周りを再設計したいので予備調査の結果を軽くまとめる
ハッシュ関係
- password_hash関数 パスワード認証用のハッシュ生成に使う
- password_verify関数 タイミング攻撃を回避するための文字列比較関数(password_hash専用)
- hash関数 通常のハッシュ生成に使う(MD5とか、SHA256とか)
- hash_equals関数 タイミング攻撃を回避するための文字列比較関数(汎用)、== や === はタイミング攻撃が可能
- パスワード認証と、それ以外で用途により使い分ける形がベストか?
暗号関係
- mcrypt_encrypt, mcrypt_decrypt PHPのコンパイル時にmcrypt対応のオプションが必要
- openssl_encrypt, openssl_decrypt PHPのコンパイル時にOpenSSL対応のオプションが必要
- mcrypt は重い (処理によっては100倍以上)かつ パディング処理に独自の癖があるためopensslの利用を推奨
暗号論的乱数生成関係
- PHP7なら random_bytes および random_int を推奨
- それ以前ならopenssl_random_pseudo_bytes および mcrypt_create_iv がお手軽
- /dev/urandom に直接アクセスするやりかたもある
- 例
- http://qiita.com/Hiraku/items/838db7d27c4fa6fb3080
- 徳丸(@ockeghem)氏の「体系的に学ぶ 安全なWebアプリケーションの作り方より」引用とのこと
- 例
CSRF対策
- ワンタイムトークン利用 に加え、POSTに限定する、リファラ―の変更がないことを確認する
- また、トークン発行画面はキャッシュされないようヘッダーを吐く
- Apacheのmod_expires、mod_headers に任せるのも一考
- ヘッダーの例
header( 'Expires: Thu, 01 Jan 1970 00:00:00 GMT' );
header( 'Last-Modified: '.gmdate( 'D, d M Y H:i:s' ).' GMT' );// HTTP/1.1の場合
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', FALSE );// HTTP/1.0の場合
header( 'Pragma: no-cache' );