こんにちは。Typetalkチームの永江です。今回は4月にリリースした、BacklogとTypetalkの連携機能である「Backlogカード」の実装の際に行った クリックジャッキング対策 について説明します。
Backlogカードとは
Backlogカードは、Typetalkのトピック内にBacklogの課題やコメントをカード形式にして表示する機能です。Backlogの課題キーや課題のURLを貼り付けるだけで、以下の画像のように表示できます(※詳しいご利用方法についてはこちらの「Typetalkのトピック上で課題の詳細を見られる Backlogカード をリリースしました!」をご参照ください)。
Backlogカードの実装は、TypetalkからBacklogに用意した埋め込み用の課題ページを<iframe>
で表示するというものです。このような実装にしたのは、もともとBacklogに<iframe>
を使った課題プレビュー機能があり、それを拡張しようとしたためです。
上の図のように外部から埋め込まれるページ(この画像の緑色の部分)はクリックジャッキングに気をつける必要があります。
クリックジャッキングとは
クリックジャッキング(クリックジャック攻撃、Clickjacking、User Interface redress attack、UI redress attack、UI redressing)は、ウェブページの利用者に対し悪意をもって使用される技術の一種で、リンクやボタンなどの要素を隠蔽・偽装してクリックを誘い、利用者の意図しない動作をさせようとする手法である。
(参照元:https://ja.wikipedia.org/wiki/クリックジャッキング )
今回クリックジャッキングを説明するために、JSFiddleで簡単なデモを作ってみました。これをクリックジャッキング対策されていないWebサービスのアカウント削除のページとしましょう。
アカウントの削除ボタンが押されるとアカウントの削除処理(実際にはアカウントの削除リクエストをWebアプリケーションに送信)をしたあとに、「アカウントの削除が完了しました。」と表示されます。
次に悪意のあるサイトです。「ここをクリック!」ボタンを押してみてください。
「アカウントの削除が完了しました。」と表示されたと思います。
悪意のあるサイトは一体何をやっているかというと、Webサービスのページを<iframe>
で埋め込んでそれをopacity: 0
で完全に透明にしています。さらに「ここをクリック!」ボタンをz-index: -1
でアカウントの削除ボタンの裏側に配置しています。
つまり、ユーザーは「ここをクリック!」ボタンを押したつもりが、実際にはWebサービスのアカウントの削除ボタンを押すことになります。
このような方法で悪意のあるサイトは、ユーザーに意図しない動作を誘導することができてしまうのです。
対策 1. X-Frame-Optionsレスポンスヘッダーを設定する
外部から<iframe>
で埋め込まれることを想定していないページに関してはX-Frame-Options
レスポンスヘッダーを適切に設定しましょう。これにより外部からページが埋め込まれるのを制限することができます。
X-Frame-Options
で指定できる値は以下のとおりです。
値 | 説明 |
DENY | 表示を拒否する |
SAMEORIGIN | 同じドメイン内のみページの表示を許可する。 |
ALLOW-FROM uri | 指定したURIのみページの表示を許可する。 |
現時点ではALLOW-FROM
はブラウザ側の未サポートやバグがあり、あまり実用的ではありません。なので基本的にはDENY
に設定し、どうしてもアプリ内でiframe
表示したいときだけSAMEORIGIN
を使うと良いでしょう。
主要なサービスの設定は以下のようになっています。
サービス名 | X-Frame-Options |
Dropbox | DENY |
GitHub | DENY |
DENY | |
Slack | SAMEORIGIN |
SAMEORIGIN |
それでは試しにBacklogの通常の課題ページと埋め込み用課題ページを<iframe>
で表示してみます。
埋め込み用課題ページは表示できましたが、通常の課題ページはX-Frame-Options: SAMEORIGIN
がついているので何も表示されませんね。
Google Chromeのデベロッパーツールで通常の課題ページのレスポンスヘッダーを見てみるとX-Frame-Options: SAMEORIGIN
がちゃんと付いているのがわかります。
このように悪意のあるサイトは<iframe>
で目的のページを呼び出すことができなくなるので、クリックジャッキングの防止に効果的です。
対策 2. iframeで埋め込み可能なページは更新処理を入れない
BacklogカードのようにすべてのWebサイトで埋め込み可能なことを前提としたページ(X-Frame-Optionsを指定しないページ)は、クリックジャッキングを避けるために更新系の処理をできないようにするべきです。そのためBacklogカードはコメントやスター等の機能は削除しています。
ヌーラボのSNSをチェック&フォローしましょう😎💐
[Instagram] https://t.co/ImPq3JKWMl
[Twitter] https://t.co/DjJ7I5mYWk
[Facebook] https://t.co/q5T1cbkb7w— Nulab Inc. (@nulabjp) 2017年6月10日
Twitterの埋め込みツイートの場合、フォローボタンを押すとこのようなページが別タブで開きます。
このページが開いた時点ではまだフォロー処理はされておらず、ユーザーがページ内のフォローボタンを押すことでフォローが完了します。
なぜこのような一見回りくどい実装になっているかというと、埋め込みツイートから直接フォローできてしまうと、悪意のあるサイトがクリックジャッキングを利用して、ユーザーの知らないうちにアカウントをフォローさせることができてしまうからです。
では、なぜ別タブで開いたページからのフォローは大丈夫なのかというと、こちらのページはx-frame-options: SAMEORIGIN
が設定してあるのでTwitter以外からのページから呼び出すことができないのでクリックジャッキングの心配がないのです。
まとめ
- 埋め込み可能なページは更新系の処理を入れないようにする
- 更新系の処理は
X-Frame-Options
が設定してあるページで行う - 埋め込まれることを想定していないページは
X-Frame-Options
の値は基本DENY
、どうしてもアプリ内でiframe表示したいときだけSAMEORIGIN
を使う
ヌーラボでは、サービスをユーザーのみなさんに安心して使っていただくために、開発だけでなくセキュリティーにも気を配れるエンジニアを募集しています!