Skip to main content

Snyk Code による Java アプリケーションでのクロスサイトスクリプティング (XSS) の防止

wordpress-sync/Blog-Design_Snyk-Code-

2023年4月25日

0 分で読めます

Java は、Web アプリケーションの HTML ページの作成にも使用できる高度なバックエンドプログラミング言語です。ただし、これらのページを作成する開発者は、XSS 攻撃に関連する潜在的なセキュリティリスクを認識しておく必要があります。最新のテンプレートフレームワークが登場したことで、適切な入力検証とエンコード技術によってセキュリティ攻撃を防ぎやすくなりました。しかし、開発者がテンプレートフレームワークを使用せずに独自の HTML ページを作成した場合、脆弱性が生じるリスクが高まります。 

たとえば、Spring MVC アプリケーションで HttpServletResponse オブジェクトを使用してコンテンツを応答に直接書き込むと、悪意のあるユーザーがページにコードを注入する機会が生じ、それが XSS 攻撃につながる可能性があります。そのため、開発者にとって、HTML ページの作成時に XSS の脆弱性を防ぐための適切な対策を実施することで、Java Web アプリケーションのセキュリティを高いレベルに保つための措置を講じることが不可欠です。

下記のような解決策によって、通常は固有の指示を伴う複雑なフレームワークを使用せずに、サーバーサイドでレンダリングされるページを簡単に実装できます。しかし、この方法には明らかな欠点がいくつかあります。

テンプレートフレームワークを使用せずに Spring MVC で HTML 出力を記述する

製品名を取得し、HttpServletResponse オブジェクトを使用してそれを Web ページに表示する Web アプリケーションがあるとします。以下は、Spring MVC コントローラーでこの機能を実装する方法の例です。

1@GetMapping("/direct")
2public void directLink (@RequestParam String param, HttpServletResponse response) throws IOException {
3   Product prod = productService.getProductByName(param);
4
5   response.setContentType("text/html");
6   var writer = response.getWriter();
7   writer.write(head);
8   writer.write("<div class=\"panel-heading\"><h1>"+ param + "</h1></div>");
9
10   String output = "<div class=\"panel-body\">" +
11           "<ul>" +
12           "<li>%s</li>" +
13           "<li>%s</li>" +
14           "<li>%s</li>" +
15           "</ul>" +
16           "</div>";
17
18   writer.write(String.format(output, prod.getDescription(), prod.getProductType(), prod.getPrice()));
19   writer.write(foot);
20
21   response.getWriter().flush();
22}

上記の Java コードによって、どのようなセキュリティ上の脆弱性が生じる可能性があるでしょうか。

Snyk Code で XSS を見つける

上の関数を注意深く見れば、少なくとも 1 つ、さらには 2 つの XSS 脆弱性に気づくかもしれません。Snyk Code を使用してアプリケーションをスキャンした場合、この方法に含まれる XSS に関する 2 つの異なる問題が通知されます。

Snyk Code を活用する方法は複数あります。3 つの異なる例を見ていきましょう。開発者が Snyk Code から最も直接的にフィードバックを得るには、IDE にプラグインをインストールします。多数の異なる IDE 用のプラグインが提供されています。以下の例では、IntelliJ プラグインが開発中に XSS の問題を見つけるのにどのように役立つかを示しています。

IntelliJ プラグインの出力:

blog-preventing-xss-product-controller

もう 1 つのオプションは、Snyk CLI を使用した Snyk Code の実行です。ターミナルからコマンド snyk code test を実行すると、以下のような出力が表示されます。この方法は、ローカルマシンや、CI/CD パイプラインにおける自動ビルドの中で役立ちます。

CLI 出力:

blog-preventing-xss-high-vulns

3 つ目のオプションが、Web UI です。この出力では、Snyk との Git 統合を使用し、https://app.snyk.io のダッシュボードを利用して GitHub リポジトリを Snyk Web UI に接続しました。この解決策では、リポジトリにコミットされたコードをスキャンして、セキュリティの脆弱性を検出します。 

Web UI 出力:

blog-preventing-xss-snyk-code-report

3 つの異なるスキャンオプションすべてで、XSS のセキュリティに関して対処が必要な 2 つの異なる問題があることが判明しました。Snyk Code により、コード内の正確な場所が特定されています。問題を分析して、それらをどのように軽減できるのかを確認しましょう。

反射型 XSS 

反射型 XSS は、ユーザーが Web アプリケーションに悪性コードを注入し、それが応答の一部としてユーザーに返されるときに発生する XSS 攻撃の一種です。示している例では、ユーザー入力が応答に書き込まれる前に適切に検証またはサニタイズされていない場合、悪意のあるユーザーがスクリプトを注入し、それが Web ページを表示する他のユーザーによって実行される可能性があります。この種の XSS 攻撃は、ユーザーデータを盗んだり、Web サイトのコンテンツを変更したり、その他の悪意のあるアクションを実行したりするために頻繁に使用されます。

上記のコードでは、HTTP リクエスパラメーターからユーザー名が取得され、以下を使用してそれが HttpServletResponse オブジェクトに直接書き込まれます。

1writer.write("<div class=\"panel-heading\"><h1>"+ param + "</h1></div>")

ユーザー入力が適切に検証またはサニタイズされないため、このコードには XSS 攻撃に対して脆弱です。たとえば、悪意のあるユーザーが「name」パラメーターに HTML コードや JavaScript コードを注入すると、Web ページを表示する他のユーザーによってコードが実行される可能性があります。

例: .../direct?param=<script>alert(document.cookie);</script> によって個人の Cookie 情報が漏洩する可能性があります。そのため、この情報が知らない間に別のサーバーに送信される可能性もあります。

Snyk Code は、93 行目で XSS を指摘することでこのミスを特定しました。

蓄積型 XSS

一方、蓄積型 XSS は、悪性コードがサーバー上に保存され、影響を受けるページにアクセスするすべてのユーザーに送られる XSS 攻撃の一種です。提供されている例では、ユーザー入力が適切に検証またはサニタイズされておらず、データベースに保存されている場合、悪意のあるユーザーがスクリプトを注入し、それが影響を受けるページを表示するすべてのユーザーに送られる可能性があります。この種の XSS 攻撃は、多数のユーザーに影響を及ぼす可能性があり、最初のインジェクションが解決された後も継続する可能性があるため、特に危険です。

上記のコードでは、ProductService から製品が取得され、それが出力文字列の一部としてフィールドに表示されます。しかし、データベースから取得された入力が適切に検証またはサニタイズされないため、このコードには蓄積型 XSS 攻撃に対する脆弱性があります。データベースへの書き込み権限を持つユーザーがはっきりしない場合は、サニタイズが特に重要です。たとえば、悪意のあるユーザーが HTML コードや JavaScript コードを含む製品説明を送信すると、それがデータベースに保存され、製品ビューにアクセスするすべてのユーザーに送られる可能性があります。 

Snyk Code は、103 行目で XSS に関するこの潜在的な問題を指摘しました。ここでは、product.description が検証やサニタイズなしで出力文字列に挿入されています。

Snyk Code で XSS の脆弱性を軽減する

XSS の脆弱性を防ぐには、ユーザー入力を応答に書き込む前に適切に検証し、サニタイズすることが重要です。Snyk Code は、すでに可能な解決策を示しています。  一つの方法として、Apache Commons Text などのライブラリを使用して入力をエンコードし、悪性コードの実行を防ぐことができます。

blog-preventing-xss-string-path

escapeHtml4() 関数を使用することで、反射型 XSS と蓄積型 XSS の両方のコードがエスケープされるため、ページの読み込み時に実行されなくなります。

当然ながら、他のライブラリでも同様のエスケープ処理を実行できます。Apache Commons Text 以外では、OWASP Encoder も利用できます。Spring を使用する場合は、Spring の HtmlUtils.htmlEscape も使用できます。

Apache Commons Text を使用する場合、適切にエスケープされたコードは次のようになります。

1@GetMapping("/direct")
2public void directLink (@RequestParam String param, HttpServletResponse response) throws IOException {
3   Product prod = productService.getProductByName(param);
4
5   response.setContentType("text/html");
6   var writer = response.getWriter();
7   writer.write(head);
8   writer.write("<div class=\"panel-heading\"><h1>"+ StringEscapeUtils.escapeHtml4(param) + "</h1></div>");
9
10   String output = "<div class=\"panel-body\">" +
11           "<ul>" +
12           "<li>%s</li>" +
13           "<li>%s</li>" +
14           "<li>%s</li>" +
15           "</ul>" +
16           "</div>";
17
18   writer.write(String.format(output,
19             StringEscapeUtils.escapeHtml4(prod.getDescription()),
20             StringEscapeUtils.escapeHtml4(prod.getProductType()),
21             StringEscapeUtils.escapeHtml4(prod.getPrice())));
22
23   writer.write(foot);

テンプレートフレームワークに関する注意事項

Thymeleaf のようなテンプレートフレームワークは、XSS の脆弱性に対する保護に役立ちます。Thymeleaf は、HTML エスケープのサポートが組み込まれた Java 用の人気のテンプレートエンジンであり、レンダリングされた HTML に含まれるユーザー入力をエンコードすることで、XSS 攻撃を防ぐのに役立ちます。

ただし、Thymeleaf はテンプレートの作成方法に大きく依存します。たとえば、前述の例のように製品をレンダリングするには Thymeleaf を次のように使用します。

1<div class="product" th:each="product : ${products}">
2  <p th:text="${product.name}"></p>
3  <p th:text="${product.type}"></p>
4  <p th:text="${product.pric}"></p>
5  <p th:utext="${product.descriptiont}"></p>
6</div>

この例では、th:text 属性はエスケープされますが、th:utext 属性はエスケープされません。この th:utext 属性は、HTML タグや特殊文字をエスケープせずにコメントテキストをレンダリングするため、XSS に対して潜在的な脆弱性があります。特定のフレームワークの使用時には、特定の要素の動作を把握することが不可欠です。

本番環境へのデプロイ前に XSS を検出する

XSS 攻撃の防止は、Java Web アプリケーションを扱う開発者にとって大きな懸念事項です。開発プロセスのできるだけ早い段階で XSS の脆弱性を特定し、それに対処することが重要です。ユーザー入力のサニタイズによって XSS 攻撃を効果的に軽減できますが、これでは必ずしも十分ではありません。

OWASP XSS チートシートXSS の Snyk Learn レッスンなどのリソースを参照して、最新の脅威や、XSS の防止に関するベストプラクティスを常に把握しておきましょう。

また、XSS に関するミスやその他のセキュリティ上の問題を、その影響が本番環境に及ぶ前に特定するための適切なツールを活用することが重要です。Snyk Code は、開発サイクルの早い段階で潜在的なセキュリティの脆弱性を特定するための貴重な無料ツールです。XSS の防止に対するプロアクティブなアプローチを採用し、適切なリソースとツールを使用することで、開発者は Java Web アプリケーションのセキュリティと完全性を確保できます。