Disqus にいくつか DOM based XSS があった件
概略
サイトのコメント欄の外部委託系サービスの disqus.comにいくつか DOM based XSS がありまして修正されました.location.hash 部分の url encode が行われない IE, Chrome, Opera で問題があったことは確認しています.
まず一つ目は,コメント欄の埋め込みスクリプトにありました.
脆弱性とその修正を確認しているのは,blogid.disqus.com/admin/universal/ にて表示されるコードを埋め込むタイプで,blogid.disqus.com/embed.js というスクリプトです.
こちらのコードは,埋め込んだドメイン上で動作していましたので,このタイプのコードを埋め込んでいたドメインで提供されているサービスに影響があった可能性があります.disqus.com ではuniversal code とは別に,特定の幾つかのブログサービス向けに専用の手順やコードを用意していますが,そちらで利用していた場合にも,影響があった可能性があります.
もう一つは,disqus.com 本体の,ログイン周りのコードです.disqus.com の幾つものページでログインしていない状態でのみ使われるコードに問題がありました.
2012/08/24 17時現在はどちらも対応済みです.
時系列
-
最初に気がついたのが,08/21 の 12時前
-
なんか disqus が色々ダメぽい
— 山田<xmp>太朗♪♪ (@t_ashula) August 21, 2012 -
実際のコードと再現手順を確認するためにアカウントを新規で作ったあと,コードを検証してコンタクトフォームから通報して,定型の応答が来たのが 08/21 の 12:40 頃.
-
その後しばらく,音沙汰が無いまま 45時間後の 08/23 の 9時過ぎに「担当チームに回したよ」とのメールが到着.
-
メールに気がついた,11時半頃に一応の修正を確認.
-
前後して,disqus の embed の status が一時的に不調に
The embed is now loading consistently and without issue. Thank you for your patience while we fixed i.. status.disqus.com/168
— DISQUS Help (@disqushelp) August 23, 2012#status -
色々確認して,13時半過ぎに直ったと Tweet.
んー.disqus の embed なコメント欄の domxss 直った.
— 山田<xmp>太朗♪♪ (@t_ashula) August 23, 2012 -
19時過ぎにそれどっち側の話?とやりとり
— mala (@bulkneets) August 23, 2012@t_ashula iframe? or 埋め込まれたドメイン上? -
08/24 14 時ごろに disqus.com 本体側のコードも修正.
-
08/24 17 時ごろにひとまず記事に
技術的な詳細
埋め込みコメント欄
disqus の埋め込みコメント欄は,埋め込まれる側の html に div#disqus_thread とスクリプトを追加してもらい,スクリプトでこの div の中にコメント欄を形成する形になってます.
コメント欄本体は disqus.com の iframe 上に作られてますが,うまく iframe が読み込めないなどに備えて,div の直下にいくつか要素が追加されます.
この追加されるコードで location.href をそのまま innerHTML に挿入している以下の様なコードがあり,div の下に iframe のコメント欄が形成される一瞬の隙をついて location.hash に載せたコードが実行可能な状態になってました.
q = f.setTimeout(function () { t.innerHTML += '<p>Loading DISQUS seems to be taking longer than usual, <a href="' + f.location.href + '">reload</a>?</p>' },1000)
記事執筆時点の実装では,onclick で location.reload() するように変更されました.
disqus.com 本体
disqus.com では,ログイン・ログアウト用のパーツの生成処理にテンプレートを使ってます.
このうちログイン用のパーツで,ログインしたあとの遷移先の指定が以下の様なテンプレートになっていました.
<li data-analytics="header login"><a rel="login" href="<%= data.urlMap.login %>?next=<%= document.location.href %>">Login</a></li>
このため,テンプレートが展開されてページの DOM に追加されるときに,location.hash に載せたコードが実行可能な状態になってました.
これが現在は,encodeURIComponent を使う形に修正されました.