Standard Taglib トピックス

メインメニュー

JSTL 最新情報

JSTL プログラミング

その他

著者専用メニュー

JSTL プログラミング - セキュリティ印刷用ページはまだ利用できません

インデックス

クロスサイト・スクリプティング脆弱性対策
執筆者:小川 環 2002.07.12更新
クロスサイト・スクリプティングとは?

Webアプリケーションの開発において、クロスサイト・スクリプティング脆弱性は、たいへん深刻なセキュリティ問題となっています。
クロスサイト・スクリプティングとは、HTML や XML の特性を利用して Web サイトの脆弱性を突くクラッキング手法です。 フォームなどへの入力時に不正な文字列(スクリプト)を打ち込むことによって Cookie の中身が別のサイトに転送され、その結果、第三者が正規のユーザになりすますといった行為を可能とさせます。 これによって、システム内にある個人情報が外部に漏洩されるという危険性が大きくなります。 他のサイトにまたがってスクリプトが実行されることから、クロスサイト・スクリプティングと呼ばれています。

原因と対策

クロスサイト・スクリプティングは、変数や文字列の値を画面上に出力する際、HTML などのマークアップ言語で定義されている一部の特殊文字をエスケープ出力させなければならない処理を、コンテンツの開発者が実装し忘れてしまうことが大きな原因となっています。
そこで JSTL では、文字列や変数の値を出力するために使用されていた <%= expression %> タグの代わりに、<c:out> および <x:out> の両タグを標準で用意しています。 これらのタグに対し escapeXml 属性を有効 ( true ) にした状態で実行させると、下の表に示されている特殊文字が自動的にエスケープ出力されるようになります。 なお、escapeXml 属性は、デフォルトで有効 ( true ) とするよう JSTL 仕様で定められています。

エスケープ文字  出力エンティティ文字 
&lt; 
&gt; 
&amp; 
&#039; 
&#034; 
例)

  <%-- 特殊文字が、まったくエスケープ出力されない --%>
  <% if (customer.getAddress() != null)  { %>
      <%= customer.getAddress() %>
  <% } else { %>
      <%= "<不明>" %>
  <% } %>
->
  <%-- 特殊文字(<,>,&,',")が、エスケープ出力される --%>
  <c:out value="${customer.address}" default="<不明>" escapeXml="true"/>

Note <c:out> および <x:out> のエスケープ文字は、基本的に XML のメタ文字を対象としています。
-> Bug 7746 ( Apache Bug Database )

関連リンク

SQL Injection 対策
執筆者:小川 環 2002.08.08更新
SQL Injection とは?

今日の Web アプリケーション開発では、SQL ベースの RDBMS と連携した事例が、たいへん日常的となっています。 そのせいか、最近になって頻繁に見かけるようになったのが SQL Injection です。 正式には、Direct SQL Command Injection と呼ばれています。
これは、フォームなどの入力時に不正な文字列 ( SQL 文 ) を打ち込み、それを Web 経由で受け取ったデータベース・サーバが完全なパラメータ値として処理せずに SQL コマンドとしてそのまま実行してしまうという、データベース・サーバを標的としたセキュリティ脆弱性です。 フォームなどに不正な文字列を入力するといった点で、クロスサイト・スクリプティング脆弱性のクラッキング手法とよく似ています。

原因

SQL Injection は、クロスサイト・スクリプティング脆弱性と同様、パラメータ値の入力チェック ( Input Validation ) を正しく処理していないことが原因となって発生します。
例えば、「フォーム上で入力した値にシングル・クォーテーション ( ' ) が含まれていると、SQL エラーが返ってくる」といった現象が発生するような場合は、特に要注意です。

コーディングに問題のあるサンプルソース(リスト1)

<%@ page pageEncoding="Shift_JIS" %>
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ page import="java.util.*, java.sql.*, javax.sql.*, javax.naming.*" %>
<%
  // データソースの取得
  Context ctx = new InitalContext();
  DataSource sample = (DataSource)ctx.lookup("java:/comp/env/jdbc/myDatabase");

  // データベースの検索
  Connection conn = sample.getConnection();
  Stamement stmt = conn.createStatement();
  String country = request.getParameter("country");
  String selectSql = "SELECT * FROM profile WHERE country = '" + country + "'";
  ResultSet profiles = stmt.executeQuery(selectSql);
%>
<html>
<head>
<title>データベース検索のサンプル</title>
</head>
<body>
<h2>検索結果</h2>
<table>
<% while (profiles.next()) { %>
    <tr>
      <td><%= profiles.getString("NAME") %></td>
      <td><%= profiles.getString("ADDRESS") %></td>
    </tr>
<% } %>
</table>
</body>
</html>
<%
  // データベース・セッションの解放
  if (profiles != null) profiles.close();
  if (stmt != null) stmt.close();
  if (conn != null) conn.close();
%>

対策 プリコンパイルされたSQLステートメントを利用する

JDBC ドライバには、java.sql.PreparedStatement という API が標準で用意されています。
この API を利用すると、プリコンパイルされた SQL ステートメントにパラメータ値をセットするよう処理されるため、シングル・クォーテーション ( ' ) などの特殊文字のエスケープ処理が不要になるどころか、パラメータ値が SQL コマンドとして機能される心配はまずありません。 なお、SQL パラメータ値をバインドする内部処理のメカニズムは、JDBC ドライバの実装に依存します。
JSTL では、java.sql.PreparedStatement を用いて SQL ステートメントを発行するように設計されています。

JSTL を用いて、リスト1を修正したソース(リスト2)

<%@ page pageEncoding="Shift_JIS" %>
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>

<%-- データソースの取得 --%>
<sql:setDataSource
  var="sample"
  url="java:/comp/env/jdbc/myDatabase"
/>

<%-- データベースの検索 --%>
<sql:transaction dataSource="${sample}">
  <sql:query var="profiles">
    SELECT * FROM profile WHERE country = ?
    <sql:param value="${param.country}"/>
  </sql:query>
</sql:transaction>

<html>
<head>
<title>データベース検索のサンプル</title>
</head>
<body>
<h2>検索結果</h2>
<table>
  <c:forEach var="row" items="${profiles.rows}">
    <tr>
      <td><c:out value="${row.NAME}"/></td>
      <td><c:out value="${row.ADDRESS}"/></td>
    </tr>
  </c:forEach>
</table>
</body>
</html>

関連リンク


Copyright (c) 2002 The Ja-Jakarta Project. All rights reserved.