診断するとなんだかんだ検出されるシリーズ:XSS:2025/02/15
- 晋次 宮田
- 2025年2月15日
- 読了時間: 4分

未だに診断をするとXSS脆弱性が見つかる現実
Webアプリケーションのセキュリティ診断を行うと、最新のフレームワークがXSS対策を組み込んでいるにもかかわらず、今でもXSS(クロスサイトスクリプティング)の脆弱性が見つかります。
その理由としては、以下のような要因が挙げられます。
開発者がフレームワークのXSS防御機能を過信している
dangerouslySetInnerHTML などの特定のプロパティの誤使用
既存のコードやレガシーシステムが最新の対策を反映していない
ブラウザの挙動によるMutation XSS(mXSS)の影響
こうした現状を踏まえ、最近の診断で実際に見つかったXSSの脆弱性を紹介します。
最近診断したXSS脆弱性の事例
事例 1:ReactアプリケーションにおけるdangerouslySetInnerHTMLの誤使用
概要
ある企業のReactを使用したアプリにおいて、dangerouslySetInnerHTML を使って動的にレンダリングされたコンテンツがありました。この部分にユーザー入力が含まれており、適切なサニタイズ処理が施されていなかったため、XSS脆弱性が発生していました。(そもそもこの名の通り、使うときには注意が必要です)
問題点
Reactは通常、JSX内のデータを自動エスケープするが、dangerouslySetInnerHTML を使用するとエスケープが行われない。Reactのエスケープメカニズムは、JSXに埋め込まれた文字列をエンコードし、<, >, &, " などの特殊文字をHTMLエンティティに変換することで、スクリプトとして解釈されないようにする。ただし、dangerouslySetInnerHTML を使用すると、このエスケープ処理が無効化され、HTMLやスクリプトがそのまま挿入されるため、XSS攻撃のリスクが生じる。
入力値の検証が不足しており、スクリプトタグを挿入できる状態だった。
攻撃の影響
攻撃者は特定のパラメータを改ざんし、悪意のあるスクリプトを挿入することで、ユーザーのセッション情報を盗み出すことが可能な状態でした。
対策
dangerouslySetInnerHTML の使用を避けるか、DOMPurifyなどのライブラリを用いて厳格なサニタイズを適用する。
必要な場合は、CSP(Content Security Policy) を適切に設定し、インラインスクリプトの実行を制限する。
事例 2:Vue.jsアプリケーションでv-htmlの誤使用
概要
Vue.jsを使ったカスタマーポータルで、ユーザーが投稿したコメントを表示する際に v-html を使用していました。この結果、入力されたHTMLがそのままレンダリングされ、XSSが可能になっていました。
問題点
v-html は危険なプロパティであり、適切なサニタイズをしないとXSSを引き起こす可能性がある。
ユーザー入力を直接表示する処理でサニタイズが不十分だった。
攻撃の影響
攻撃者は、コメント欄に <script>alert('XSS!')</script> などのスクリプトを埋め込むことで、閲覧したユーザーのセッション情報を窃取できる状況だった。
対策
v-html の使用を避け、エスケープ済みのデータのみを表示する。
どうしてもHTMLを扱う必要がある場合は、DOMPurifyなどのサニタイズライブラリを適用する。
Vue 3のv-safe-html(サニタイズ機能付き)を利用する。v-safe-html は、Vueの公式プラグインではなく外部ライブラリですが、DOMPurifyを活用して安全なHTMLレンダリングを提供します。たとえば、以下のように実装することで、外部から受け取ったHTMLを適切にサニタイズしつつ表示できます。
<template>
<div v-safe-html="sanitizedContent"></div>
</template>
<script>
import VueSafeHtml from 'vue-safe-html';
import { createApp } from 'vue';
const app = createApp({
data() {
return {
sanitizedContent: '<p>安全なコンテンツ</p>'
};
}
});
app.use(VueSafeHtml);
app.mount('#app');
</script>
このように、v-safe-html はサニタイズ機能を備えており、XSSのリスクを軽減できます。ただし、より安全を確保するためにはCSPやTrusted Typesと組み合わせるのが理想的です。
あらためてやったほうが良いこと
XSSの脆弱性は今でも発見され続けており、フレームワークの機能だけを頼りにするのは不十分です。以下のポイントを再確認し、XSSリスクを最小限に抑えるべきです。
1. 危険なプロパティの使用を避ける
dangerouslySetInnerHTML(React)
v-html(Vue.js)
innerHTML(純粋なJavaScript)
bypassSecurityTrustHtml(Angular)
これらのAPIどうしても使う必要がある場合は、DOMPurifyなどの安全なサニタイズ処理を必ず組み合わせるようにしましょう。
2. CSP(Content Security Policy)の適用
script-src 'self' や nonce を使用し、不正なスクリプトの実行を制限する。
unsafe-inline を禁止し、インラインスクリプトの使用を避ける。
3. Trusted Typesの活用
ChromeやEdgeでは require-trusted-types-for 'script' を導入することで、XSSのリスクを大幅に軽減できる。
Trusted Typesを利用することで、危険な文字列をDOMに直接挿入することを制限できる。これは、ブラウザがスクリプト関連の危険な操作(例えば、innerHTML や eval())に対して、開発者が事前に定義したセーフリストに従った型のみを許可する仕組みである。例えば、window.trustedTypes.createPolicy を使用して安全な型を定義し、それを適用することで、XSSリスクを低減することができる。ChromeやEdgeなどの最新ブラウザが対応しており、CSPと併用することでより強固な防御が可能となる。
4. 定期的な脆弱性診断を実施する(一応宣伝)
セキュリティテストをCI/CDパイプラインに組み込み、自動的に脆弱性を検出する。
WAF(Web Application Firewall)を適切に設定し、不正なリクエストをブロックする。
手動診断も定期的に行い、新たな脆弱性の発見に努める。(連絡お待ちしております)
5. フレームワークのセキュリティアップデートを定期的に適用
React、Vue、Angularなどのフレームワークは、セキュリティアップデートが随時提供されているため、最新バージョンを使用する。これはおすすめですが、実際問題やるタイミングが難しいですね。



