特集

次世代XML Webサービスを試す Part 2

− WS-Security詳細解説 −

1.WS-SecurityとWeb Services Enhancements

インフォテリア株式会社
吉松 史彰
2003/01/29 改訂 (改訂前の記事はこちら

Page1 Page2 Page3 Page4 Page5

 本稿は、「Web Services Development Kit Technology Preview」をベースとして2002/11/15に公開された同名の記事を、正式版である「Web Services Enhancements」に対応させ全面的に加筆・修正を行った改訂版です。

Back Issue
1
XML超入門

始めに

 前回はWeb Services Enhancements for Microsoft .NET(以下WSE)を紹介して、簡単なプログラムで動作の確認を行った。今回は、WS-Security仕様の実装をより詳細に確認していくことにしよう。

WS-SecurityとWSE

 WS-Securityは、SOAPヘッダを利用してメッセージレベル・セキュリティを実現するためのフレームワーク仕様である。現在公開されている仕様はIBM、Microsoft、VeriSignの3社によって2002年4月に発表された。その後、標準化活動の場としてOASISが選ばれ、現在はOASISのWeb Service Security Technical Committeeにて仕様策定が行われている。当初発表された仕様は、MicrosoftやIBMのWebサイトで確認することができる。これについては、日本のマイクロソフトのホームページに参考訳が掲載されている。

 ここでWS-Securityを「フレームワーク」と定義したのは、SOAPメッセージを保護するための仕組みがWS-Security仕様には具体的に定義されていないからだ。例えばSOAPメッセージ全体、あるいはその一部にデジタル署名を施してメッセージの完全性(Integrity)を保証する方法としてXML署名仕様を利用することが規定されているだけで、具体的なデジタル署名の方法やその検証方法を定義しているわけではない。ユーザーの「ログイン状態」を保持するためのセキュリティ・トークンの授受についても定義されているが、実際にどうやって認証をするのか、その結果どのようなトークンを作成するのか、といった具体的内容は、それぞれの認証プロトコルに委ねられている。それら具体的手順で作成された具体的データを、どのようにSOAPメッセージに乗せて運べばいいか、という抽象的内容を決めているのがWS-Security仕様である。このため、仕様書自体にも抽象的な記述が多く、読んでも分かりづらいことがあるかもしれない。だが、具体的内容を決めないことで、今後も数多く出てくるであろう、XMLベースのセキュリティ仕様を柔軟に取り込めるようになっているのだ。

 WSEには、上記の当初発表版のWS-Security仕様と、その後2002年8月に発表されたWeb Services Security Addendum日本語版はこちら)の2つの仕様が実装されている。Web Services Security Addendum(補遺)は、当初のWS-Security仕様ではあいまいであったり、場合によってはセキュリティ・ホールになりかねない記述について補足するために作られた。

 WSEでは、WS-Security仕様に規定されている内容のうち、主に次の4つに関する実装を提供している。

  • ユーザー名とパスワードを使ったセキュリティ・トークンによるメッセージ認証
  • X.509v3証明書を使ったセキュリティ・トークンによるメッセージ認証
  • SOAPメッセージの一部または全体に対するデジタル署名
  • SOAPメッセージの一部または全体に対する暗号化

セキュリティ・トークンとは何か

 WSEでは、ユーザー名とパスワードの対を使ってセキュリティ・トークンを作成することができる。セキュリティ・トークンという観点からは、パスワードはオプションである。WS-Security仕様によると、「セキュリティ・トークンとは、申告のコレクションである」と定義されている。また、「申告(Claim)とは、その送信元の宣言である」と定義されている。例えば、WS-Security仕様には次のようなセキュリティ・トークンの作成法が定義されている。これは、「送信元はuser1である」という申告を1つだけ含むセキュリティ・トークンである。なお、申告を相手に掲示することを「表明(assert/assertion)」という。例えば、次のセキュリティ・トークンを送信するということは、「『送信元はuser1である』という申告を表明している」と考えられる。

<wsse:UsernameToken
    xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
  <wsse:Username>user1</wsse:Username>
</wsse:UsernameToken>
『送信元はuser1である』という申告を表明するセキュリティ・トークンの例

 申告には、「保証されている(endorsed)申告」と「保証されていない(unendorsed)申告」の2種類がある。送信元でも受信側でもない第3の機関によって保証されているかいないかによって、申告はこの2つに分けられるのだ。例えば、X.509v3証明書に含まれている「自分は誰それである」という申告は、その証明書を発行したCA(Certificate Authority:認証機関)によって保証されている。しかし、上記のようなユーザー名だけが含まれた申告は、誰からも保証されていない。従って、上記のセキュリティ・トークンに含まれる申告は保証されていない申告ということになる。

 保証されていない申告に使い道がないわけではない。ごく限られたノードしかアクセスできないネットワークでは、ノードにアクセスできることそのものがすでにセキュリティ上の関門になっているため、ネットワーク自体が信頼されている場合がある。そのような場合は、そのネットワーク上を流れているということを理由にセキュリティ・トークンに含まれる申告を信頼することもできるわけだ。

 また、保証されていない申告の使い道を高めるもう1つの有名な手段として、「所有の証明(proof-of-possession)」の提供という方法がある。所有の証明とは、申告者が、申告者とその申告が信頼できるかどうかを評価する者(簡単にいうとサーバ)しか知らないことになっている秘密を正しく所有していることの証明である。これを提供すれば、評価者は申告の内容を信頼するかどうかの判断ができる。難しく説明したが、要するにクライアントとサーバしか知らないことになっているパスワードを提供することで、クライアントが本当に名乗っているとおりのクライアントであることを証明するわけだ。所有の証明も一種の申告(自分がパスワードを知っているということの申告)なので、次のようにセキュリティ・トークンに含むことができる。

<wsse:UsernameToken
    xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
  <wsse:Username>user1</wsse:Username>
  <wsse:Password>pass1</wsse:Password>
</wsse:UsernameToken>
「所有の証明」としてパスワードを提供するセキュリティ・トークンの例

 ただし、上記のセキュリティ・トークンを受け取って、<wsse:Password>要素を所有の証明の正しい申告として評価することはまずないだろう。パスワードが平文で送られているので、この電文を盗み見た誰かがuser1をかたっている可能性が捨てきれないからだ(もっとも、伝送路がSSLなどを利用して暗号化されていれば信頼できるかもしれないので、平文はまったく利用価値がないわけではない)。そのため、当初のWS-Security仕様にはもう1つ、平文パスワードをSHA-1アルゴリズムでハッシュしたダイジェストを、さらにBase64でエンコードした文字列で送信する仕組みを規定している。こうすれば、伝送路が暗号化されていなくても、のぞき見によってパスワードそのものが盗まれてしまう心配がなくなる。

<wsse:UsernameToken
    xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
  <wsse:Username>
    user1
  </wsse:Username>
  <wsse:Password Type="wsse:PasswordDigest">
    8FePHnF0saQcTqjG4X96ijuIySo=<
  /wsse:Password>
</wsse:UsernameToken>
平文パスワードからハッシュを生成し、さらにエンコードした文字列を含むセキュリティ・トークンの例

 だが、実はダイジェストの仕組みでもセキュリティ上は不十分なことがすでに知られている。セキュリティに詳しい人には、「リプレイ攻撃」とひと言いえば済むだろう。確かに、上記のセキュリティ・トークン(を表すXML 1.0のデータ)をのぞき見ても、パスワードそのものは分からない。だが、パスワードが分からなくても、上記が所有の証明として正しいことさえ分かれば、悪意を持ったクライアントは、このXML 1.0を丸々コピーして、自分のSOAPメッセージにヘッダとして付けてしまえばよい。メッセージを受け取った側から見れば、正しいパスワードを正しい手順でエンコードした結果が送られてくることに変わりはないので、このセキュリティ・トークンを信頼してしまう可能性があるのだ。

 この問題に対処するため、WS-Securityを発表した3社は、2002年8月に発表した「Addendum(補遺)」(日本語版)でこの問題への解決策を公開した。補遺には、リプレイ攻撃を防ぐ有名な手法であるノンス(nonce:「その場限りの」「1回だけの」といった意味)とタイムスタンプを使って、ダイジェストに手を加える方法が規定されている。例えば、ノンスとタイムスタンプの両方を利用する場合は、次のような手順でダイジェストを作成する。

  1. ノンスの生成(ノンスはランダムなバイト列)
  2. タイムスタンプの生成
  3. タイムスタンプをUTF-8でエンコードしたバイト列を作成
  4. パスワードをUTF-8でエンコードしたバイト列を作成
  5. 1と3と4を足したバイト列を作成
  6. 5をSHA-1でハッシュしてダイジェストを作成

 このようにして作成されたダイジェストと、ノンスかタイムスタンプ(あるいは両方)をセキュリティ・トークンに含めて送ることで、パスワードのダイジェストが常に変化するようになり、同じダイジェストを繰り返し送信する攻撃を検出できるようになる。補遺では、このようにして作成されたダイジェストを次のようにXML化してセキュリティ・トークンに含む手順を規定している。

<wsse:UsernameToken
    xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext"
    xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
  <wsse:Username>
    user1
  </wsse:Username>
  <wsse:Password Type="wsse:PasswordDigest">
    QDyo4ErAJDzbHSajgWq0EuyYSbY=
  </wsse:Password>
  <wsse:Nonce>
    qBfQGsF9xMM/PUgwJTNOYQ==
  </wsse:Nonce>
  <wsu:Created>
    2002-10-20T09:09:08Z
  </wsu:Created>
</wsse:UsernameToken>
ノンスとタイムスタンプを用いて生成したパスワードのダイジェストを含むセキュリティ・トークンの例
 

 INDEX
  特集 次世代XML Webサービスを試す Part 2
  WS-Security詳細解説
  1.WS-SecurityとWeb Services Enhancements
    2.セキュリティ・トークンと認証
    3.セキュリティ・トークンとしてのX.509v3証明書
    4.SOAPメッセージの完全性
    5.SOAPメッセージの秘匿性
 
 「特集:次世代XML Webサービスを試す」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間