私の J2EE/Java コードの一部では、getRequestURI()
XSS 攻撃を防ぐためにサニタイズするために の出力に URLEncoding を実行しますが、Fortify SCA では検証が不十分であると見なされます。
なんで?
重要な点は、HTMLの特殊文字をHTMLエンティティに変換する必要があるということです。これは、「HTMLエスケープ」または「XMLエスケープ」とも呼ばれます。基本的に、文字、、、、およびは、、、、、<
およびに置き換える必要があります。>
"
&
'
<
>
"
&
'
URLエンコーディングはそれを行いません。URLエンコードは、URL特殊文字をパーセントエンコードされた値に変換します。これはHTMLエスケープではありません。
Webアプリケーションの場合、HTMLエスケープは通常、ユーザー制御の入力を再表示するビュー側で実行されます。Java EE Webアプリケーションの場合、使用しているビューテクノロジによって異なります。
Webアプリが最新のFaceletsビューテクノロジーを使用している場合は、自分でエスケープする必要はありません。Faceletsはすでに暗黙的にそれを行います。
WebアプリがレガシーJSPビューテクノロジを使用している場合は、JSTL<c:out>
タグまたはfn:escapeXml()
関数を使用してユーザー制御の入力を再表示していることを確認する必要があります。
<c:out value="${bean.foo}" />
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
Webアプリが非常にレガシーであるか、設計が不適切で、サーブレットまたはスクリプトレットを使用してHTMLを印刷している場合は、より大きな問題が発生します。HTMLエンティティをエスケープできるJavaメソッドは言うまでもなく、組み込みのタグや関数はありません。自分でメソッドを作成するかescape()
、ApacheCommonsLangStringEscapeUtils#escapeHtml()
を使用する必要があります。次に、ユーザーが制御する入力を印刷するすべての場所で使用していることを確認する必要があります。
out.print("<p>" + StringEscapeUtils.escapeHtml(request.getParameter("foo")) + "</p>");
JSTLでJSPを使用するように、レガシーWebアプリを再設計する方がはるかに優れています。
URL エンコーディングは、一重引用符 ( ) や括弧などの特定の重要な文字には影響しない'
ため、URL エンコーディングは変更されていない特定のペイロードを通過します。
例えば、
onload'alert(String.fromCharCode(120))'
一部のブラウザーでは、タグ内に挿入されるとコードが実行される可能性のある有効な属性として扱われます。
XSS を回避する最善の方法は、すべての信頼できない入力をプレーン テキストとして扱い、出力を構成するときにすべてのプレーン テキストを適切なタイプの出力に適切にエンコードすることです。
セキュリティの追加レイヤーとして入力をフィルタリングする場合は、フィルターがすべての引用符 (バックティックを含む) と括弧を可能なコードとして扱い、その入力に意味がない限りそれらを許可しないようにしてください。