SAMLは悪しき設計の温床か?複雑怪奇な認証プロトコルを斬る
SAML: A fractal of bad design
SAML: A fractal of bad design
SAML(Security Assertion Markup Language)が抱える設計上の複雑さと、それに伴うセキュリティリスクを「フラクタル(自己相似的な複雑さ)」と表現し、その不完全さを批判する議論が巻き起こっています。多くの実装において発生する互換性の問題や、認証フローの深すぎる階層構造が、いかに開発者の頭を悩ませているかが論点となっています。
SAMLは記事で説明されている以上に酷いよ。署名が実際に何を検証しているのかを確認する必要がある、といった問題があるからね。でも将来には楽観的かな。汎用的なXMLパースのような多くの機能を持つライブラリに頼るんじゃなくて、SAMLのサブセットと主要な10社程度のプロバイダーのダイアレクト(方言)だけをサポートすればいい。かなりニッチなプロバイダーについては、案件の規模的に見合う場合のみ、アドホックに追加すれば十分だよ。
いわゆる「委員会設計(design by committee)」ってやつだね。全員を会議室に集めて、誰かの都合の良いユースケースを損なうようなトレードオフが誰も決められない状況。結局、設計など何もできず、ただ設計が存在しうる枠組みを作っただけっていう。WireguardとOpenVPNを使ったことがある人なら、その違いがすぐに分かるはず。OpenVPNは委員会設計の産物で、Wireguardはビジョンを持った誰かによる、目的の定まった設計だ。OpenVPNは多くのことができるけど、もしWireguardのユースケースに合うなら、Wireguardの方がはるかに優れている。OSIスタックとIPの間にも同じことが言えるよね。OSIは身元証明、回線確立、セッション、料金計算、コレクトコール、サービス品質……といったすべての要素を盛り込もうとした。IPはそれを見て、「そんな騒音は無視だ。パケットを送る。届かなければ再送する。これだけでいい」と言ったわけ。IPはOSIモデルに無理やり当てはめられているから教えられてはいるけれど、実際にOSIスタックなんて誰も使っていない。X.509もWebPKI証明書の雛形として再利用されただけだしね。XML対JSONも同じ。XMLはマークアップテキスト用に作られたはずだけど、JSONで見るとすごく醜い。でもそのユースケースですら、XMLは複雑すぎるんだ。もしIPやWireguard、JSONの設計者がSSOシステムを作ったら、認証先にtelnetかHTTPでログインして、トークンを取得し、それをサービス側にコピペする。そしてサービス側が認証先にトークンの有効性とユーザー名を問い合わせて完了、という形になったはず。あとは誰かがコピペを自動化するブラウザ拡張を作るか、iframeに埋め込むだけ。それなのに、今のこの状況は何なんだろう。プロトコルの複雑さはバグの隠れ家であり、脆弱性の温床だ。異なる実装間での非互換性を生む原因にもなる。それも多くの場合、意図的にね。とにかくひどいよ。設計するならちゃんと意見を持つべきだ。そうしないと何も設計していないのと同じ。もしすべてのユースケースを網羅できないなら、残りをカバーする別のものを設計すればいいだけのことだよ。
まさに「おっ!マークアップ言語だ!何でも解決できそう!」という産物だよね。認証なんて、マークアップを必要とするドキュメントやデータストリームじゃないのに。記事がこれをXMLと結びつけたのは正しいよ。当時はまさに、あらゆる釘に対してXMLというハンマーを振り回していたからね。でも、この問題はまだ終わっていないと思う。OIDCはGoogleなどの都合に合わせて多くの前提条件を抱えているし、言及されているTailscaleでさえ、「一線を守る」と言いつつも、GitHubアカウントなどの扱いが変わると綻びを見せている。私たちに欠けているのは、プロバイダーに依存しない方法だ。自分で管理するバックエンドを使って、どこでもアカウント作成とログインができるようになるべきだよ。それは可能だけど、今の技術スタックでは無理だね。
少数派かもしれないけど、SAMLが輝く領域もあると思うよ。1. OIDC/OAuth2はリクエストをサービスプロバイダー側から発信する必要があるけど、多くの企業向けIDPはIDP主導のフローができるからSAMLに頼っている。2. SAMLのセキュリティはペイロード自体に組み込まれているから、MITM攻撃に対して保護できる。HTTPSも理論上は同じ保証があるけど、実際にはSSLオフロードがアプリケーションサーバーではなく別の場所で行われることも多いからね。投稿者はSAMLの脆弱性リストを挙げているけど、OIDC/OAuth2で同じ比較をしないのは公平じゃないと思う。結局のところ、これらはツールであり、その有効性はツールを理解して使いこなすスキルの高さに大きく依存するよ。
一番好きなSAMLの恐怖体験は、かつて主要なxmlsigのC言語実装のデフォルト設定で、公開鍵で署名をチェックするだけでなく、こんなことまでしていたことかな。・攻撃者が制御するドキュメントで指定されたパスワードを使って、HMACでチェックする。・Web PKIを使って署名をチェックする(つまり攻撃者が自分の個人ドメインのTLSキーでSAMLドキュメントに署名すれば、常に有効と見なされる)。正直、SAMLを使っているサイトがなぜ常時ハッキングされていないのか不思議だよ。絶対的にひどい規格よりも、さらにひどいのは、その実装そのものだね。
聞かなきゃいけないんだけど、これって例の有名な「https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/ 」のパロディなのかな?
SAMLはクソだけど、企業向けのSSOという狭いユースケースにおいてOIDCにはない機能がまだ色々あるんだ。特にIdP主導フローは代表例だね。OIDCは製品によってサポートがバラバラな仕様の寄せ集めだけど、SAMLの一般的に実装されているサブセットは、その平凡さゆえに、まあまあ安定している。いずれOIDCがSAMLに取って代わるだろうけど、企業向けに売るなら両方サポートすべきだね。いずれにせよ、どっちを使ったとしても、各IDP間のSCIMの不整合に対処する時間に比べれば大したことじゃないけど。
この記事に対する公正な批判としては、SAMLの脆弱性は挙げているのにOIDCで同じ比較をしていないことかな。OIDCにも独自のバグがあるよ。JWTアルゴリズムの混乱、noneアルゴリズム攻撃、オーディエンスチェックの漏れ、JOSEライブラリの不具合などだね。
「さらに、委員会が何度も会議を重ねるやり方は、何でもあり(kitchen-sink)なプロトコル設計のレシピになってしまう(例えばウォーターフォール開発や、ビッグデザイン・アップフロントなど)」……個人的には、何でも入っているのが結構好きなんだけどね。
OIDCはプライベートネットワーク内のIdPでは動作できない。SAMLならできる。一般的に、SAMLが複雑なのは (1) 認証自体が複雑だから (2) XMLが複雑だから (3) 正規化や署名が複雑だから、この3点に尽きるよ。