この記事はtraPアドベントカレンダー2019の32日目の記事です。一般的なアドベントカレンダーだと今日が1日目の記事なんですけどね。
おひさしぶりです。ながてち(@nagatech)です。
今年も残すところあと1ヶ月ですけど、みなさん、卒論の進捗どうですか?
僕はこの記事を書きながら明日(12/2)発表の卒論構想発表の発表資料を作っています。助けてください。
なぜこの日に書けると思ってしまったのか...
(追記: 卒論構想発表は無事に終わりました)
それは置いておいて、今回は最近traP部員に向けてリリースした部内サービスの紹介と、その開発中に見つけた脆弱性でVue.js製のライブラリ「Vuetify」にコントリビュートした話を書きたいと思います。
部内サービス「booQ」
ブックと読みます。ロゴは「booq」と小文字なので部内の表記揺れが激しいです。
どのようなサービスかをざっくり言うと、サークルの備品管理ツールであり、書籍の知見共有ツールであり、部員の貸し借り支援ツールであるような部内向けサービスです。
実際にどういう仕上がりになっているかはbooQ開発チームメンバーの一人の@ryohaくんが書いてくれた記事をみてもらえると嬉しいです。
部内の備品・書籍管理サービスbooQの新規開発 | 東京工業大学デジタル創作同好会traP
余談ですが、この部内サービスの開発にあたってのGitHubの活用法について、技術書典6で本を書いたので、興味のある方は読んでくださると嬉しいです。
BOOTHで電子書籍版が今すぐ買えます(ダイマ)。
traP SysAd TechBook | traP SysAd班
本当は工大祭前リリースに向けてチームメンバー全員でデスマーチした話とか、リリース直後に使用できないレベルのバグを引き起こした話とか、そもそも工大祭が開催されずにbooQが使われなくて悲しい思いで突発的にラジオ配信した話とかを書きたかったのですが、卒論がやばいのでまた別の機会に書きたいなとか思っています。
booQ開発中に脆弱性を見つけた話
今回はこれをメインに書きます。
実際にどういう脆弱性かを説明する前に、booQのカレンダー機能の説明をしたいと思います。
booQのカレンダー機能
これは実際にリリースされている本番環境のスクリーンショットです。
booQでは別な人から物品(本など)を借りる際に、返却期限を指定することができます。返却期限を指定した場合、画像のようにダッシュボードにカレンダーが表示されて、どのような物品を借りたのか、いつ返せばいいのか、返却期限がすぎていないかなどの確認ができます。
今回見つけた脆弱性はこのカレンダーに関連したものになります。
前提として、booQプロジェクトはクライアントサイド(Vue.js)のCSSフレームワークとして、「Vuetify」を使用しています。
見つけたVuetifyの脆弱性
まずはこちらのスクリーンショットをご覧ください。
これはbooQのダッシュボードにアクセスした瞬間の画像です。ページの色が大変なことになっています。
これは何が起こっているのかというと、物品の名前をHTMLタグで囲むことで、HTMLが解釈されて実行されています。スクリーンショットはカレンダーに表示されている物品の<style>body{filter:invert(1)}</style>
が実行された状態になります。
上の画像にはカレンダーが写ってないのでカレンダー単体で見ると、カレンダーの名前の部分でHTMLが解釈されていることが分かります。これは物品名が<b>bold</b>
です。
booQでは部内限定のサービスでありながら、この脆弱性を放置できない理由がありました。それは、traP部員であることの認証のために部内SNSであるtraQのAPIへのアクセスのためのトークンをクライアント側で保持している設計なので、アクセストークンが取得できれば部員の誰でも別な部員に成り済ますことができるというXSS脆弱性の問題がありました。
そのため、Vuetifyのカレンダーの実装を書き換える必要がありました。
実際に行ったこと
コードの修正
ざっとVuetifyのカレンダーのコードを読んだところ、原因はカレンダーのイベント名を代入するところで、<
が<
などにエスケープされてないことでした。カレンダー以外の実装でエスケープされてる部分あるやろ〜とか思ったら本当にescapeHTML
なる関数が実装されていたのでそれをカレンダーに適用することですんなり問題は解決しました。なので、実際のコード変更は1行だけです。
検証環境の作成
VuetifyのContributeのドキュメントを読みながら検証環境を用意しました。
すんなり環境が用意できて、自分のコードがちゃんと動くことを確認できました。ここらへんのエコシステムがしっかりしてるからOSSとして成功しているんだろうなあ...。
プルリクエスト作成
今回はマジで変更を取り込んで欲しかったので、変更のモチベーションについて解説したり、比較画像を用意したり、いろいろ頑張りました(もちろん英語です)。ここに一番時間がかかったかもしれないです。
実際に作成したプルリクエストがこちらになります。
マージされました🎉
一週間くらい待ったらいきなりマージされました。
その次の日には変更が取り入れられたバージョンがリリースされました。
すぐさま最新バージョンにアップデートすることで、問題は解決されました。
下のスクリーンショットは色がおかしくなる<style>body{filter:invert(1)}</style>
がカレンダーに表示されてもなにも起こらなくなった図です。
おわりに
この記事では最近リリースした部内サービスの簡単な紹介と、その開発を通してOSSコントリビュートすることができたことを書きました。
OSSにプルリクエストを出してマージされるくらいエンジニアとして成長できたんだなあと一人でしみじみ思っています。
ただ、これは自分一人だけの力で行ったことではなく、SysAd班の人たちにいろいろ助けてもらいながらできたことだと思っています。脆弱性について開発チーム外にもかかわらずいろいろ検証してくれた人たち(特に@spaと@sappi_red)には感謝申し上げます。
本当はもっといろいろ書きたかったのですが、12月1日が終わりそうだったのと、ゼミ発表の12月2日が近づいて来てるので締めさせていただきます。(発表資料完成してないよどうしよう...)
明日12月2日の担当は@azulene_c10h8さんと@shirodoniさんです。
お楽しみに!