Webアプリ ホームページ npm XSS攻撃

DOMPurifyを使い悪意のあるHTMLを排除しようとした話

目的

今回ブログを作成する画面は入力画面と表示画面が1画面の左右に配置されるように設計しました。

左の画面に入力すると右に実際のデザインで表示され、バランスを見ながら記事を書くことができます。

マークダウンという書き方も考えましたが仕事柄HTMLに触れることが多いのでHTMLでかけたらいいなと思い画面を作成しました。

ここで気を付けなければいいけないのがXSS攻撃です。

HTMLに意図しないscriptが組み込まれそれを実行してしまうと自分のホームページが犯罪に使われてしまう恐れがあります。

例えばポストに onerror 属性付きの画像タグが紛れていれば、描画された瞬間に任意のJavaScriptコードを走らせることができます。

onerror属性とは

画像が存在しなかった場合のjavascriptを定義することができます。
<img src="x" alt="x" />

Xという画像が存在しないとonerror以下のスクリプトが実行され、今回の場合cookieが外部に送信されてしまいます。

写真を記載したい場合imageは必要不可欠ですが、何もチェックをしないと今回のように悪意あるスクリプトが紛れ込み、重大なセキュリティ事故を起こしかねません。

そういった悪意あるHTMLから危険な要素、属性を除去するライブラリがDOMPurifyになります。

設定内容

html = DOMPurify.sanitize(html, { ALLOWED_TAGS: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'p', 'br', 'span','strong', 'strong', 'em', 'del', 'ul', 'ol', 'li', 'blockquote', 'code', 'pre', 'a', 'img', ], ALLOWED_ATTR: [ 'id', // 見出しアンカー用 'class', // divのクラス用 'href', // aタグ用 'src', // imgタグ用 'alt', // imgタグ用 'target', // aタグ用 'rel', // aタグ用 ], ALLOW_DATA_ATTR: false, // イベント属性を明示的に禁止 });

ALLOWED_TAGSは許可リストを設定します。

自身が利用するものを設定しましょう。

DOMPurifyはデフォルトでon属性を除去してくれますがALLOW_DATA_ATTRで明示的に禁止しても問題ありません。

<a href="https://www.npmjs.com/package/dompurify?activeTab=readme" target="_blank" rel="noreferrer noopener">DOMPurify</a>

ちなみにリンクを設定するときrelは必須です。

そのためALLOWED_ATTRでrelを許可しています。

DOMPurify