
XSS攻撃の概要とそのリスク
XSS攻撃は、ユーザー入力が適切に「サニタイズ (*1)」されずにWebページへ埋め込まれることで発生します。たとえば、コメント欄に入力されたスクリプトがそのままHTMLとしてレンダリングされる場合、攻撃者は任意のJavaScriptを実行できます。
これにより、セッションの乗っ取り、個人情報の窃取、偽装コンテンツの表示などが可能となります。
DOMPurifyは、このような入力データを安全に処理するための強力なツールであり、信頼性の高いサニタイズ機能を提供します。
(*1) サニタイズとはユーザーからの入力データに含まれる危険な要素(=悪意あるコードや意図しない制御文字列)を無害化、または除去する処理を指します。
DOMPurifyの基本とセットアップ
DOMPurifyは、HTML、SVG、MathMLのコンテンツをサニタイズし、危険なスクリプトや属性を除去するライブラリです。軽量で設定も容易なため、モダンなWebアプリケーションに適しています。
まず、DOMPurifyをプロジェクトに導入する方法を説明します。以下は、CDNを利用してDOMPurifyをHTMLファイルに組み込む例です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>XSS対策ハンズオン</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.1.6/purify.min.js"></script>
</head>
<body>
<h1>DOMPurifyデモ</h1>
<textarea id="input" rows="5" cols="50"></textarea>
<button onclick="sanitizeInput()">サニタイズ</button>
<div id="output"></div>
<script>
function sanitizeInput() {
const input = document.getElementById('input').value;
const clean = DOMPurify.sanitize(input);
document.getElementById('output').innerHTML = clean;
}
</script>
</body>
</html>
このコードをブラウザで実行し、テキストエリアに <script>alert('XSS');</script>
と入力して「サニタイズ」ボタンをクリックしてください。
DOMPurifyによりスクリプトタグが除去され、安全なテキストのみが出力されます。
ハンズオン:ユーザー入力のサニタイズ
実際にDOMPurifyを使ったサニタイズのプロセスを体験しましょう。以下のシナリオを想定します。
あるWebアプリケーションで、ユーザーのコメント投稿を可能とする。コメントにはHTMLタグを部分的に許可したいが、スクリプトや危険な属性は除去したい。
DOMPurifyの設定をカスタマイズして、特定のタグのみを許可する例を示します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>カスタムサニタイズデモ</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.1.6/purify.min.js"></script>
</head>
<body>
<h1>カスタムサニタイズ</h1>
<textarea id="input" rows="5" cols="50"></textarea>
<button onclick="sanitizeCustom()">サニタイズ</button>
<div id="output"></div>
<script>
function sanitizeCustom() {
const input = document.getElementById('input').value;
const clean = DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['p', 'strong', 'em'],
ALLOWED_ATTR: ['style']
});
document.getElementById('output').innerHTML = clean;
}
</script>
</body>
</html>
このコードでは、ALLOWED_TAGS
で <p>
, <strong>
, <em>
を許可し、ALLOWED_ATTR
で style
属性を許可しています。
<script>
や onerror
などの危険な要素は自動的に除去されます。
たとえば:
<p style="color: blue;">安全なテキスト</p>
→ 保持される<script>alert('XSS');</script>
→ 削除される
DOMPurifyの高度な設定とベストプラクティス
DOMPurifyは柔軟にカスタマイズ可能です。たとえば:
FORBID_TAGS
で特定のタグを明示的に禁止ADD_ATTR
で独自属性を許可
などの設定が可能です。
また、セキュリティ関連ライブラリは脆弱性対応のため頻繁に更新されるため、定期的な更新が重要です。
以下のベストプラクティスを推奨します:
- 常に最新バージョンのDOMPurifyを使用する
- 許可するタグ・属性は必要最小限に限定する
- サニタイズ後の出力も、サーバー側で検証する
これらにより、多層防御を実現し、さらに安全性を高めることができます。
実際のアプリケーションでの応用
DOMPurifyは、ブログのコメント欄、チャットアプリ、CMSのコンテンツ入力など、ユーザー生成コンテンツを扱う多様な場面で活用可能です。
たとえば、ReactアプリケーションでDOMPurifyを使用する場合、以下のように実装できます。
import React, { useState } from 'react';
import DOMPurify from 'dompurify';
const App = () => {
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
const handleSanitize = () => {
const clean = DOMPurify.sanitize(input, {
ALLOWED_TAGS: ['p', 'strong', 'em'],
ALLOWED_ATTR: ['style']
});
setOutput(clean);
};
return (
<div className="p-4">
<h1 className="text-2xl font-bold">ReactでのXSS対策</h1>
<textarea
className="w-full p-2 border"
rows="5"
value={input}
onChange={(e) => setInput(e.target.value)}
></textarea>
<button
className="mt-2 p-2 bg-blue-500 text-white"
onClick={handleSanitize}
>
サニタイズ
</button>
<div
className="mt-4 p-2 border"
dangerouslySetInnerHTML={{ __html: output }}
></div>
</div>
);
};
export default App;
このReactコンポーネントは、ユーザー入力をサニタイズして安全にレンダリングします。
dangerouslySetInnerHTML
を使用する際は、必ずDOMPurifyなどのサニタイズ処理を行うことが重要です。
まとめ
DOMPurifyは、XSS攻撃を防ぐための強力かつ柔軟なツールです。
本記事では:
- 基本的なセットアップ
- カスタム設定
- 実際のアプリケーションでの応用
をハンズオン形式で解説しました。
セキュアなWeb開発においては、適切なサニタイズとライブラリの更新が不可欠です。
DOMPurifyを活用することで、ユーザー生成コンテンツを安全に取り扱い、信頼性の高いアプリケーションを構築できます。