日々のいろいろ

【Flatt Security XSS Challenge】DOMPurifyとtextareaについて

投稿日: 5/21/2025

Flatt Security XSS Challengeについて

2024年の11/12 ~ 11/29に開催されていました、3問のXSS問題です。
まだ現時点では公開されているようなので、問題と解答・解説のリンク貼ります↓。
問題:https://challenge-xss.quiz.flatt.training/?beatme
解答・解説:https://speakerdeck.com/flatt_security/jie-da-jie-shuo-flatt-security-xss-challenge

高難易度とのことですが、とりあえず取り組んでみました(やっと消化)。

ちなみに、本記事の内容は最初のChallenge 1についてだけです。
Challenge2, 3は正直解説読んでも全くわかりません。

本題

対象のリンクにアクセスすると、以下のページが表示されました。
messageパラメータが付与されてます。
画像

いろいろスクリプトの挿入を試します。
コメントアウトしてみたり, </textarea><script>alert(origin);</script>としてみたり...
タグとして認識されるものの、アラートは実行されません。CSPヘッダは使われてないし。

即解答を確認

ここで、ソースコードも公開されていることを知りました。
ふむふむ、HTMLのテンプレートエンジンであるEJSと、サニタイズにDOMPurifyを使っているようです。
なるほど、これで単にscriptタグを挿入しても無害化されたことで、サブミット後のtextareaからスクリプトが消されていたのですね。

さてさて、解答としてはid属性としてDOMPurifyに認識させる、という手法でした。
解答のスクリプト:<div id="</textarea><script>alert(origin);</script>"></div>

以下がXSS後のHTMLです。
描画されると、textareaが不正に閉じられ、スクリプトがそのまま実行されたことがわかります。
</div>なしで挿入した場合もXSS成功し、直後のHTMLは同じでした。後はなんでもよさそうです。DOMが破壊されて変な画像のようになったりしてます。

DOMPurifyでは、divタグのid属性が有効で</textarea>~が無効で、サニタイズ後の描画では親となるtextareaが有効になり、divタグが無効になりました。
画像

対策は?

解答には、

<%- sanitized %>

ではなく

<%= sanitized %>

としてtextarea内の文字列エスケープをちゃんと行うといったものです。(下記参照)
HTMLタグが文字列として描画されてますね。
画像

おわり

なるほどー、DOMPurifyのバイパスについては調べてみると面白そうです。
textareaの扱い含めて、開発側も攻撃手法を知りつつ対策する必要がありますねー。


コメント

まだコメントがありません

コメントする
0 / 1500 文字