本記事の目的
セキュリティエンジニアのmaximaです。
日頃は、主にアプリケーションのセキュリティ改善に取り組んでおります。
本日は、NEアドベントカレンダー17日目です。
先日、社内で脆弱性に関する勉強会を実施しました。
テーマは XSS(クロスサイト・スクリプティング) と セッションハイジャック です。
IPAの「安全なウェブサイトの作り方」をベースに、
- 脆弱性の基本的な考え方
- どういう仕組みで起きるのか
- 実際に何ができてしまうのか
といった話をしつつ、ローカル環境でXSSやセッションハイジャックを実際に体験する講座も行いました。
本記事は、社内で実施した脆弱性に関する勉強会でご説明した内容をもとに、記事として再編したものです。
XSSは、
ウェブアプリケーションにスクリプトを埋め込むことが可能な脆弱性がある場合、これを悪用した攻撃により、
利用者のブラウザ上で不正なスクリプトが実行されてしまう
(IPA 安全なウェブサイトの作り方 改定第7版 p.22より引用)
という脆弱性です。
詳細な説明や、具体的な対策方法については、IPA 安全なウェブサイトの作り方 をご参照ください。
本記事では、XSSの中でも、特に信頼境界横断型XSS(Cross-Boundary Stored XSS) が現代のサービスでいかに脅威となり得るか、その「怖さ」を一段深く理解するための啓蒙を目的としています。
※ 本記事では、 外部から入力されたデータが、一度は信頼されるサービスや仕組みを経由して保存され、その後、別の信頼境界においてXSSとして発火する構造を、便宜上 「信頼境界横断型XSS(Cross-Boundary Stored XSS)」 と呼びます。(※これは一般的なセキュリティ用語ではなく、本記事における造語です)
本記事の位置づけ
本記事は特定のサービスや実装を示すものではなく、 一般的な設計上の注意点を整理したものです。
具体的な攻撃方法を示す意図はありません。
XSSと聞いて思い浮かぶ、昔ながらのイメージ
XSSというと、古典的な例としてよく挙げられるのが、
- 誰でも書き込めるチャットサービス
- 掲示板やコメント欄
に、悪意のあるユーザーがスクリプトを仕込む、いわゆる「いたずら的な行為」です。
実は私自身も、今から20年近く前、よく使っていた掲示板で似たような経験をしています。
ある日突然、
- 文字サイズが異常に大きく
- 背景が真っ赤
- 文字がピンク
という、とても読む気になれない状態になっていました。
当時は「なんだこれ……」くらいの感覚でしたが、今思えば完全にXSSでした。
こうした経験があると、
「XSSって、見た目を壊されるくらいの“いたずら”でしょ?」
という印象を持ってしまうのも、無理はないと思います。
「掲示板特有の問題」だと思っていませんか?
さらに、XSSは
- 誰でも書き込める掲示板
- 不特定多数が利用するサービス
に特有の問題だ、と感じている人も多いかもしれません。
一方で、最近のサービスはどうでしょうか。
昨今は、ログインすると、そのユーザー専用のページが生成される、いわゆる SaaS型のサービス が急増しています。
このタイプのサービスでは、ユーザーがXSSになる文字列を書き込んだとしても、影響を受けるのは自分の画面だけに見えます。
そのため、
「ログイン後の個人ページしかないなら、 XSSでいたずらしても自滅するだけでは?」
と考えてしまう人も少なくありません。
本当に「自分だけ」で終わるでしょうか?
たしかに、そのページに書き込めるのが本人だけなら、その認識は正しいです。
しかし、ここで一度立ち止まって考えてみてください。
- そのページにアクセスするのは、本当に本人だけでしょうか?
- 書き込めるのは、本当に本人だけでしょうか?
- XSSでできることは、本当に「見た目を壊す」だけでしょうか?
「信頼境界横断型XSS(Cross-Boundary Stored XSS)」とは
信頼境界横断型XSS(Cross-Boundary Stored XSS)という用語自体は、先に示しましたように、本記事での造語です。
Cross-Boundary Stored XSSとは、外部から入力されたデータが、一度は信頼されるサービスや仕組みを経由して保存され、その後、別の信頼境界においてXSSとして発火する構造のことです。
通常のStored XSSは、データベースに入っている値に、XSSが成立するような文字列があり、それが展開されることで、XSSが成立するというものです。
Cross-Boundary Stored XSSも、データベースに入っている値ではありますが、そのデータをデータベースに挿入したのが、画面を操作している当人ではなく、「信頼されている別のサービス」「内部システム」「連携先API」など、本来は攻撃者であることを想定していない第三者である点が特徴です。
具体的な例を以下に提示します。
例1:銀行API連携サービスの場合
たとえば、銀行の入出金履歴をまとめて可視化するサービスを作るとします。
銀行は、あらゆるサービスの中でも最上位クラスのセキュリティが求められる存在です。
銀行そのものが攻撃者になる可能性は、現実的にはほぼ考えなくてよいでしょう。
では、銀行を使う人はどうでしょうか。
もっと言えば、銀行に振込をする人はどうでしょうか。
銀行には「摘要欄」があります。
振込は誰でも行えます。
銀行側は当然、自社サイトで表示する際には、適切にエスケープ処理を行います。
しかし、APIで連携する際は、多くの場合
エスケープされていない生の文字列が送られてきます。
これは設計として自然です。
銀行側でエスケープしてしまうと、連携先で二重エスケープが発生してしまう可能性があるからです。
もし、あなたのサービス側でXSS対策が不十分で、
摘要欄をそのままHTMLに埋め込んで表示してしまったらどうなるでしょうか。
銀行自体は無害でも、
銀行を経由した第三者の入力によって
あなたのサービス上で、Cross-Boundary Stored XSSが発動する可能性があります。
※ 銀行の振込摘要欄については、実際には使用できる記号が制限されており、
入力できる文字数も少ないため、ここで挙げたようなXSSが成立するケースは
現実的には多くありません。
本記事ではあくまで「外部入力が、信頼できるサービスを経由して
自分のサービスに流れ込む」という構造を説明するため、
イメージしやすい例として取り上げています。
例2:ECサイト連携の場合
この構造は、ECサイトでも同じです。
- 注文者名
- 住所
- 備考欄
- 配送指示
- ギフトメッセージ
これらはすべて、注文者になりすました第三者が自由に入力できる文字列です。
もし、これらの値を、APIで自動で取り込んで、画面に表示するようなシステムを構築する場合、その際の表示方法には、細心の注意を払う必要があります。
ECサイト自体に悪意はなくても、
「その先」にいる人間の入力は信頼できません。
例3:その他、よくある落とし穴
銀行やEC以外にも、同じ構造を持つ例はたくさんあります。
- 問い合わせフォームやサポートチケットなどの外部入力を扱う画面
- メール連携や外部通知を取り込んで表示する管理画面
- アクセスログ・操作ログ・監査ログなどの閲覧画面
- CSVなどの外部データをインポートし、プレビュー表示する機能
- チャットツールや通知サービスと連携したWebhook経由の表示
- OAuth / SSO などで取得したプロフィール情報の表示
- IoT・医療・工場などの現場データを扱う管理ダッシュボード
これらに共通しているのは、
連携先のサービスは信頼できても、
その先の「人間の入力」は信頼できない
という点です。
これらのサービスすべてで、Cross-Boundary Stored XSS が成立し得ます。
特に管理画面や内部ツールでは、
- 内部だから安全
- 表示するだけだから大丈夫
という思い込みから、XSS対策が抜け落ちやすくなります。
XSSの先にある、本当のリスク
入力可能な文字数が多くなると、
- 多彩なXSS攻撃が可能になり
-
fetchAPI やXMLHttpRequestを使った POST送信まで許してしまう
ケースも出てきます。
ここまで来ると、
- 金銭が動く処理
- 重要な設定変更
といった操作が、ユーザーの意図しないタイミングで実行される可能性が出てきます。
これが業務システムやインフラ管理、医療・物流などの分野で起きた場合、
結果として人の安全や生命に影響を及ぼすケースも、理論上は否定できません。
まとめ
XSSは、
- 古典的
- いたずらっぽい
- 今さらな脆弱性
と思われがちです。
しかし実際には、
現代のSaaS・API連携・管理画面の世界でこそ、
影響範囲が大きく、致命的になりやすい脆弱性
です。
素朴で古典的な脆弱性のように思えてしまいがちですが、発生した際の脅威は、非常に大きくなることもあります。
「ログイン後だから安全」
「内部ツールだから大丈夫」
「信頼できるサービスと連携しているから問題ない」
その前提こそが、XSSの入口になることがあります。
本記事が、そうした前提を一度立ち止まって見直すきっかけになれば幸いです。

