JVN iPedia という脆弱性対策情報データベースの Webサイトがあるのですが、そこに載っていた JVNDB-2016-005868 という脆弱性情報について調査する過程を紹介します。
調査
まず、JVNDB-2016-005868 をよく読みます。
JVNDB-2016-005868
MoinMoin における “JavaScript インジェクション” 攻撃を実行される脆弱性概要
MoinMoin には、”JavaScript インジェクション” 攻撃を実行される脆弱性が存在します。
本件は、action=fckdialog&dialog=attachment コンポーネント (ページ名経由) に影響のある “クロスサイトスクリプティング (XSS)” に関する脆弱性です。
これだとよく分かりません。MoinMoin にクロスサイトスクリプティング (XSS) という脆弱性があったらしいですが、MoinMoin が何なのか分かりません。「JavaScript インジェクション」というのは、「クロスサイトスクリプティング (XSS)」とほぼ同じ意味であると理解して良いでしょう。
もう少し下を見ると、
影響を受けるシステム
MoinMoin
- MoinMoin 1.9.8
と書いてあります。どうやら、「MoinMoin」というシステムが存在するようです。XSS の脆弱性があったということなので、Webサイトで使用するものなのでしょう。
そこで、Googleで「MoinMoin」検索してみると 一番上に出てきました。この Webサイトで間違いないでしょう。
このトップページに、
The MoinMoin Wiki Engine
と書いてありますので、Wiki を作るための Webアプリケーションであることが分かります。
JVNDB-2016-005868 に戻って、「想定される影響」のところを読みます。
想定される影響
第三者により、”ページ作成または巧妙に細工された URL” のアプローチを利用されることで、”JavaScript インジェクション” 攻撃を実行される可能性があります。
URLに JavaScriptのコードを埋め込むと、それが画面のどこかにそのまま出力され、コードが実行されてしまうようです。
次に、少し先の「共通脆弱性識別子(CVE)」を見ます。
共通脆弱性識別子(CVE) CVEとは?
この脆弱性には、「CVE-2016-7146」という名前がつけられていることが分かります。
少し戻って「ベンダ情報」のとこを見ます。
(今回の場合、ベンダというのは MoinMoin を提供している組織を指しています)
ベンダ情報
MoinMoin
- MoinMoin : MoinMoinDownload
- Security Fix Announcements : XSS in GUI editor’s attachment dialogue CVE-2016-7146
この中の 2つ目のリンクは、MoinMoinの脆弱性に関するページになっています。
そちらのページで CVE-2016-7146 という文字を探すと、次のように バージョン 1.9.8 で修正されていると記載されています。
1つ目のリンクは、MoinMoin のダウンロードページです。このダウンロードページを見てみると、「Repositories」(リポジトリ)のURLも載っています。リポジトリというのは、ソースコードが保管されているデータベースのことです。
リポジトリのURLは 2種類あり、それぞれ「1.9」と「2.0」という文字が入っていますが、これはバージョンを表していると予想できます。今回は バージョン 1.9.8 で修正された脆弱性なので、1つ目の http://hg.moinmo.in/moin/1.9 をクリックします。
開いたページの中の「changes」という欄に、CVE-2016-7146 という文字があります。このリンク先を見れば、CVE-2016-7146 に対する修正内容が分かるはずです。ここをクリックします。
(Mercurialという分散バージョン管理システムを使っているようです)
まず、左の赤枠にあるのが、このファイル名です。MoinMoin/action/fckdialog.py
となっており、拡張子が .py
ですので、これは Python というプログラミング言語で記述されたファイルであることが分かります。
その下にソースコードが表示されていますが、赤色が修正前の内容、緑色が修正後の内容になります。その色のついた部分の1つ目はファイルの最終更新時刻ですので無視すると、修正箇所は 1行だけのようです。
修正前
attachmentsPagename = requestedPagename or request.page.page_name
修正後
attachmentsPagename = requestedPagename or wikiutil.escape(request.page.page_name)
request.page.page_name
という変数がそのまま使われるのではなく、wikiutil.escape()
というメソッドに渡されて処理された結果が使われるように変更されています。
もう少し詳しく調べるために、右の赤枠内にある file というリンクをクリックし、このファイル全体を見てみます。このファイルは何百行とあるのでどこを見たらよいのか分からないかもしれませんが、先程の “wikiutil.escape(request.page.page_name)
” という文字列で、ブラウザのページ内検索すればすぐに修正箇所に移動できます(ここです)。 Pythonは割りと分かりやすい文法のプログラミング言語ですので、Pythonを知らない人でも、プログラミングが分かる人であれば、だいたい何をやっているのか予想が付くのではないかと思います。
このあたりのソースコードを見ると、少し後のところで HTMLの文字列を生成しており、この中で先程のrequest.page.page_name
が出力されているようです。ですので、この変数に JavaScriptのコードが入っていたら実行されてしまい危険ですので、HTMLエスケープ処理が必要だったわけです。
ここであらためて request.page.page_name
という変数についてですが、これは「(request
: HTTPリクエスト情報) の中の (page
: ページに関する情報) の中の (page_name
: ページ名)」を表しているのでしょう。Wikiは、ユーザーがページを作る時に指定するページ名が URLに入ることが多いので、WebブラウザからHTTPリクエストされた時のURLからページ名を取得してここにセットしているのだと思います。また、wikiutil.escape()
というのは、HTMLエスケープというXSS対策の処理を行っているのだと予想できます。実際に http://hg.moinmo.in/moin/1.9 の中のファイルをいろいろ解読してみるも、この予想は間違ってないようです。HTMLエスケープに Welcome | Werkzeug (The Python WSGI Utility Library) というライブラリを使っていることや、URLにはやはりページ名が含まれていることも分かりました。このあたりの詳細は話が込み入るため省きますが、以下のファイルが参考になります。
- http://hg.moinmo.in/moin/1.9/file/1563d6db198c/MoinMoin/wikiutil.py
- http://hg.moinmo.in/moin/1.9/file/1563d6db198c/MoinMoin/wsgiapp.py
まとめ
このように脆弱性情報から辿っていって実際のソースコードを調査することができます。
今回は、修正されたコードが 1行しかなく拍子抜けしましたが、逆に言えばこれだけで対策が済んでしまうということです。信頼できない値が入っている可能性のある変数を HTMLに出力する場合は、HTMLエスケープすることで XSSが防げるのですが、そういう箇所が多いと今回のように漏れが発生します。ですので、デフォルトで HTMLエスケープが適用されるような仕組みにしておき、その必要ない箇所だけ例外的に扱うのがよいでしょう。Webアプリケーションのテンプレートライブラリには、HTMLエスケープする場合の出力方法より、HTMLエスケープしない場合の出力方法の方が面倒なやり方にしているものもあります。
ウェブサイトのセキュリティに関しては、こちらを参考にして下さい。