説明
Jakarta Facesの標準コンポーネントh:outputText、h:outputFormat、h:outputLabelは、HTML/XMLマークアップに意味を持つ文字を既定でエスケープします。escapeをfalseにすると保護が無効になり、値がマークアップとして表示されます。ユーザー入力などの信頼できないデータが含まれる場合、攻撃者が実行可能なHTMLやスクリプトを挿入するおそれがあります。
escape="false"だけで攻撃が成立するわけではなく、信頼できない値がその出力へ到達する必要があります。ただし、既定の出力エンコードを回避する設定なので、データの取得元と変換処理を確認してください。Jakarta Faces 4.1のVDL文書では、3つのコンポーネントの既定値をtrueと定義しています。
想定される影響
- 被害者の権限による操作やアカウントのなりすまし
- ページに表示された機密情報の閲覧・外部送信
- フィッシング画面の挿入、内容の改ざん、悪意のあるサイトへの誘導
対処方法
- 通常のテキストは
escapeを省略するかescape="true"を指定し、既定のエスケープを維持してください。 - 入力検証や文字列フィルターで出力エンコードを置き換えないでください。実際の出力コンテキストに合わせて値をエンコードしてください。
- ユーザーが作成するリッチHTMLが必要なら、維持管理されているOWASP Java HTML Sanitizerなどの最小限の許可リストポリシーで、サーバー側で無害化した値だけを表示してください。
escape="false"を使う箇所のポリシーとデータ経路を確認し、sanitizeという関数名だけで安全と判断しないでください。 - CSPは追加の防御として使い、出力エンコードやHTMLの無害化の代わりにしないでください。
例
変更前
html
<ui:composition xmlns:ui="jakarta.faces.facelets"
xmlns:h="jakarta.faces.html">
<h:outputText value="#{profile.biography}" escape="false" />
</ui:composition>
変更後
html
<ui:composition xmlns:ui="jakarta.faces.facelets"
xmlns:h="jakarta.faces.html">
<h:outputText value="#{profile.biography}" />
</ui:composition>
説明:
- 変更前: ユーザーが編集できる紹介文を
escape="false"で表示するため、値のマークアップがブラウザーに解釈されます。 - 変更後:
escapeを省略して既定値trueを使い、同じ値をHTMLテキストとしてエンコードします。
参考資料
- Jakarta Faces仕様一覧
- Jakarta Faces 4.1
h:outputText - Jakarta Faces 4.1
h:outputFormat - Jakarta Faces 4.1
h:outputLabel - Jakarta Expression Language 6.0
- OWASP Cross Site Scripting Prevention Cheat Sheet
- OWASP Java HTML Sanitizerリリース
- OWASP ASVS 5.0
- CWE-79
- OWASP Top 10:2025 A05 - Injection
- OWASP Top 10:2021 A03 - Injection