一部のSAMLライブラリの脆弱性の詳細

複数のSAMLライブラリに認証を回避できる脆弱性があると明らかになりました。
JVNVU#98536678: 複数の SAML ライブラリに認証回避の脆弱性

どういう脆弱性なのかが書いてあり、かつ簡単に理解可能だったので詳細を書いていきます。
Duo Finds SAML Vulnerabilities Affecting Multiple Implementations | Duo Security

要約

簡単に説明すると、認証した結果のデータを改ざんすることで別のユーザになりすませてしまう問題です。

本来なら署名が存在するため改ざんしても検出されてしまいます。
ただし、XMLの署名には意味的に同じであれば表現方法が違うデータであっても同じとして見なす仕様があります。
そのため、問題のあるライブラリでただしく取り出せないような表現方法にデータを改ざんすることで、別のデータをライブラリに読み込ませることができてしまうと言う問題です。

SAMLの署名

SAMLの認証の流れで、認証した結果誰なのかを認証する側のサービスが認証をお願いした側のサービスに送ってきます。

この中には以下のように認証したユーザの情報と、改ざん防止のために署名が含まれています。
この例ではNameIDの値に入っている[email protected]が認証に成功したというデータになります。

<!-- これは階層構造とかを大幅に省略しています -->
<SAMLResponse>
  <NameID>[email protected]</NameID>
  <SignatureValue>BASE64_TEXT</SignatureValue>
</SAMLResponse>

ここでNameIDの値を書き換えたとしても、署名した結果がSignatureValueにあるため、それを検証すれば書き換えられたとわかります。
そのため、別のユーザへのなりすましを回避できています。

XMLの正規化

XMLは以下のように、意味を変えずに属性の順番を変えたり空白やコメントを入れられます。

<A C="2" B="1">text</A>

<A B="1"
   C="2"
>te<!-- comment-->xt</ A >

この2つのXMLはハッシュ値が違いますが実際には同じ内容であり、これで署名が一致しなくなるのは困る場合があります。

そのため、XMLの署名では正規化(canonicalization)を定義しています。
正規化によって形式をそろえた状態で署名を検証することで、予期せぬ表現の違いで署名が一致しなくなるという事を防いでいます。

一般的には以下のURLの方法で正規化が行われるそうです。
この正規化ではコメントを削除しない仕様であり、例に挙げたXMLは同一とはみなされません。
しかし、一般的にはだいたいの場合コメントも削除するようです。
(今回の問題はこの違いも影響している)

Exclusive XML Canonicalization Version 1.0

問題となるライブラリの挙動

例えば以下のNameIDのユーザAとユーザBがいたとします

ユーザA
<NameID>[email protected]</NameID>

ユーザB(.calはgoogleが持っているトップレベルドメインで実在します)
<NameID>[email protected]</NameID>

このとき、ユーザBが以下のようにNameIDを書き換えます
<NameID>[email protected]<!-- comment -->l</NameID>

署名の検証時の正規化でコメントを削除する実装の場合、書き換え前と同じ状態になるため正常と判断されます。
署名が正常であるためSAMLライブラリはNameIDの値を取り出しますが、このときNameIDの中身にはコメントが含まれているため、XML的には以下の3つのノードとして取り出されます。

[
  {text: '[email protected]'},
  {comment: 'comment'},
  {text: 'l'}
]

きちんとtextを接続することで本来認証したユーザである [email protected]を取り出すことができ、元のユーザとして認証できます。

ですが、一部のライブラリでは最初のノードだけをみて判断している場合があます。
そのような場合、NameIDが[email protected]として取り出してしまうため、ユーザBがユーザAとしてログインできてしまいます。
(コメントが無い場合は最初のノードだけをみても上手く動き、ここにコメントを入れるような場合は滅多に無いので気がつきにくいな…といった感じです)

まとめ

  • XMLの正規化でコメントの処理がおかしいため、コメント付きでも署名が一致してしまう
  • NameIDにコメントが含まれている場合に、文字列の途中までしか取り出さない

といった2つの問題の組み合わせにより、別のユーザになりすませてしまうという問題が起きていました。

なお、既にライブラリ側では修正されているため、アップデートするだけで解決します。

また、元の記事ではSSOであれば他にも色んなシーケンスがあるため途中で突破できない、多段階認証をしているのであればその1段が突破されるだけなので影響は少ないといった点があり、場合によっては攻撃が成功しないパターンもあるそうです。

参考資料