mod_auth_ticket - Bringing Single-Sign-On to lighttpd

19
mod_auth_ticket による サーバ丸ごと SSO 化と lighttpd モジュール作成体験 @tyamadajp

description

Explains mod_auth_ticket, a newly developed module for lighttpd to make any website SSO-enabled. Also discusses development experience for lighttpd and some strength evaluation of crypto used by this module.

Transcript of mod_auth_ticket - Bringing Single-Sign-On to lighttpd

Page 1: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

mod_auth_ticketによるサーバ丸ごとSSO化とlighttpdモジュール作成体験

@tyamadajp

Page 2: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

lighttpd とは

apache nginx lighttpd thttpd稼動に必要な

メモリやリソース △ ○ ○ ◎機能や

モジュール資産 ◎ ○++ ○ △おおまかな性能

(条件による) △ ◎ ○ ○非サーバー的

使いやすさ × × × ○モジュール開発

API充実度 ○ ○ △ ×モジュール間の

連携 ○ ○ △ ×モジュール追加

容易性 ○ △ ○ ×

開発の活発度 ◎ ○ △ ×

Page 3: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

こんな状況に最適● マシンリソースは節約したい● そこそこ性能と機能は欲しい● 自分で拡張したい● 後からモジュール構成を

ちょこちょこいじりたい

普通のサーバーでも使えますが、こういうシンクライアント転用の自宅サーバーで使用中

Wyse S90

HP t5730

Page 4: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

mod_auth_ticket● OpenIDなどのSSOでサーバ全体を保護する● 各種アプリでの対応は不要

(ユーザ管理をどうするかにより若干手を入れる必要はある)

静的ファイルアプリ1/PHP

アプリ2/Perlアプリ3/Ruby

mod_auth_ticket

認証ブリッジ(RP)

IdP

Page 5: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

mod_auth_ticket● OpenIDなどのSSOでサーバ全体を保護する● 各種アプリでの対応は不要

(ユーザ管理をどうするかにより若干手を入れることもある)

静的ファイルアプリ1/PHP

アプリ2/Perlアプリ3/Ruby

mod_auth_ticket

認証ブリッジ(RP)

IdP

各種SSO結果をm_a_tの対応形式で暗号化・署名して保護ページに再度リダイレクト

ベーシック認証相当に見せかける

RP発行のトークンの破棄・更新

Page 6: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

メリットとデメリットメリット● どんなコンテンツ・SSO方式にも容易に対応● 特別な設定なしにログにユーザ別の履歴が残る● サーバ内アプリ間移動で再認証が不要で高速● 対ユーザはForm認証、対アプリはBasic認証と

UI構成や開発が楽な方向で見せかけられる

デメリット● サーバの管理権限が必要● そのSSO方式に対応済のアプリと干渉する

(そのアプリについては外さないと無駄な再認証が起きたり)

Page 7: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

設定例(と lighttpd の応用)

$HTTP["url"] =~ "^/login/" { setenv.add-environment = ( "MAT_NAME" => mat_name, "MAT_KEY" => mat_key )}else $HTTP["url"] =~ "^/" { auth-ticket.loglevel = 255 auth-ticket.override = 2 auth-ticket.timeout = 3600 auth-ticket.name = mat_name auth-ticket.key = mat_key auth-ticket.options = "path=/; httponly;" auth-ticket.authurl = "/login/"}

RPの設定

m_a_tの設定

Page 8: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

設定例(と lighttpd の応用)

静的ファイルアプリ1/PHP

アプリ2/Perlアプリ3/Ruby

mod_auth_ticket

認証ブリッジ(RP)

IdP

各種SSO結果をm_a_t指定の形式で暗号化・署名して保護ページに再度リダイレクト

ベーシック認証相当に見せかける

$HTTP["url"] =~ "^/login/" { setenv.add-environment = ( "MAT_NAME" => mat_name, "MAT_KEY" => mat_key )}else $HTTP["url"] =~ "^/" { auth-ticket.name = mat_name auth-ticket.key = mat_key}

常にm_a_tと RPのキー情報が一致する必要がある

暗号化・署名

Page 9: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

設定例(と lighttpd の応用)

# generate "var.mac_name" and "var.mac_key"include_shell "/.../lighttpd-make-mat-key.sh"

$HTTP["url"] =~ "^/login/" {・・・以下先程の設定・・・

$ cat lighttpd-make-mat-key.sh#!/bin/shmd=$(dd if=/dev/urandom bs=1 count=16|md5sum)set -- $md

cat <<EOFvar.mat_name = "CHID"var.mat_key = "$1"EOF

ロード時にコマンドを実行して、その結果を設定として取り込める。これで毎回変わる(※)共通キーを自動生成

※マシン起動時は同じになる問題が…

Page 10: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

まとめ(1)● アプリ/コンテンツ関係なしにサーバ全体を

SSO認証下に置く mod_auth_ticketを作ってみた● 複数アプリ雑居サーバの認証管理に便利● 今のところGoogleAccountでテスト(実利用中)

→他のSSO方式にもRPページ1枚で対応● lighttpdは旬を過ぎた感もあるけど便利

公開中&今後の予定● https://github.com/tai/mod-auth-ticket-for-lighttpd

● 互換モジュールをapacheに移植するかも…

Page 11: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

lighttpd モジュールの作り方intmod_auth_ticket_plugin_init(plugin *p) { p->name = buffer_init_string("auth_ticket") p->version = LIGHTTPD_VERSION_ID; p->init = module_init; p->set_defaults = module_set_defaults; p->cleanup = module_free; p->handle_uri_clean = module_uri_handler; p->data = NULL;

return 0;}

initで初期化、set_defaultsで設定を読み込み、h_u_cで設定に基づいて処理して、cleanupで終了処理

Apacheや nginxに比べてシンプル(やや機能は↓)

Page 12: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

lighttpd モジュールのデータ構造

typedef struct { PLUGIN_DATA;

plugin_config **config; plugin_config conf;

array *users;} plugin_data;

lighttpd.conf内の{}コンテキスト毎に生成されるp_cのリスト

上のコンテキスト別の設定を合成し、「今の実行コンテキストで有効になっている」設定

具体的なplugin_configの中身はモジュール毎に自由。 p_cはコンテキスト毎に生成されるのでコンテキストに因らない情報ならplugin_dataに直接収容できる

initで生成し、以後受け渡されてゆくデータ構造

※上はm_a_tの場合

Page 13: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

モジュール作成での比較

apache nginx lighttpdマルチプロトコル

対応 /フック多様性 ○ ○ ×

メモリ管理階層型プールap_*(p, ...)

階層型プールngx_p*(p, ...)

単一バッファbuffer_*(...)

提供されるデータ構造やAPI

libapr参照

汎用のものもHTTP特有のも、充実度はnginxとapacheは同格

ngx_buf_t,ngx_array_t,ngx_list_t,ngx_hash_t,ngx_rbtree_t,ngx_url_t,...他多数

buffer, array, stream位?

とにかく少ない&未整理な感じ

ステージ粒度やモジュール連携の

柔軟性かなり細かい かなり細かい やや粗目

モジュールのビルド

apxsで外部ビルド

./configure--add-module=で静的リンク

Makefile.am 編集で一括ビルド or同一ビルドオプションで外部ビルド

Page 14: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

まとめ( 2 )● まとめてみると… lighttpdは手間かかるorz● apache最強。しかしnginxもよく考えられてる● nginxにDSOをロードするモジュールを

静的リンクしておくと幸せになれる気がしてきた

Page 15: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

困っていること

静的ファイルアプリ1/PHP

アプリ2/Perlアプリ3/Ruby

mod_auth_ticket

認証ブリッジ(RP)

IdP

各種SSO結果をm_a_t指定の形式で暗号化・署名して保護ページに再度リダイレクト

ベーシック認証相当に見せかける

平文で送るmod_auth_cookieより安全だが、RP<->m_a_tの連携がどの程度安全か実は図りかねてる

ココ

Page 16: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

何をやっているか

静的ファイルアプリ1/PHP

アプリ2/Perlアプリ3/Ruby

mod_auth_ticket

認証ブリッジ(RP)

in(=認証結果の情報)out(=暗号化した状態)

● in→outの転送時に平文のままはNG● 幸い、長さが短いので擬似乱数列と XORしている● しかし、毎回同じだとモロバレ● そこで、時刻 tを saltに使って乱数列を捻る● 更に、同時刻でもinが違えば outが異なるよう

直前バイトとも XOR

Page 17: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

安全?な受け渡し(1)function make_cookie($key, $data) {

$now = time();

$now = $now - $now % 5; #5秒毎にキー変更

$tmp = md5($now . $key, TRUE);

$enc = bin2hex(

encrypt($data,$tmp,strlen($tmp)));#暗号化

$sig = md5($key . $now . $enc); #署名

return "crypt:" . $sig . ":" . $enc;

}

Page 18: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

安全?な受け渡し(2)#要はbuf[i] = rand[i] ^ buf[i] ^ buf[i-1]

function encrypt($buf, $key, $keylen) {

$n = strlen($buf);

for ($i = 0; $i < $n; $i++) {

$c = ord($buf[$i]); #IV=0なのが微妙↓

$c ^= ($i > 0 ? ord($buf[$i - 1]) : 0)

^ ord($key[$i % $keylen]);

$buf[$i] = chr($c);

}

return $buf;

}

Page 19: mod_auth_ticket - Bringing Single-Sign-On to lighttpd

まとめ( 3 )● お遊びサーバならいいが…● こういうやつの「安全性」の評価方法は?● 乱数列 +XOR自体は安全、でも…

● それに時刻(=絞り込み可能)を加えたら?● それをMD5したら? MD5(rand)の乱数性は?● IV=0で折り畳みXORした時の脆弱度は?

–既知平文攻撃でアウトか…

先生、もっと知識(&想像力)が欲しいです…

※そういうわけで、コメント大歓迎