Webセキュリティの小部屋

Twitter のフォローはこちらから Facebook ページはこちら RSSフィードのご登録はこちらから
公開日:2013年12月15日
最終更新日:2020年8月13日

Like 句に対する SQL インジェクション対策(Java編)

概要

SQL インジェクションは、プレースホルダを利用することで対策が可能ですが、Like 句のワイルドカードついては、ほとんどの情報元が「別途エスケープが必要です」としか記載されていません。

この記事では、SQL Server に対するワイルドカードのエスケープ方法の、Java の具体的例を紹介します。動作確認環境は、JDK 6 + Tomcat 7 + SQL Server 2012 です。

JDK が 6 なのは、SQL Server の JDBC ドライバが、まだ JDK 7 をサポートしていないためです。

サンプルアプリケーションの概要は、以下の通りです。

search

SQL Server のワイルドカードのエスケープ

SQL Server のワイルドカードのエスケープに関しては、以下の記事を参考にしてください。

実装例

・input.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<html>
<body>
<h1>名前検索</h1>
  <form action="/test/search" method="post">
     名前:<input type="text" name="name">
     <input type="submit" value="送信">
  </form>
</body>
</html>

・search (Search.java)
import java.io.IOException;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Properties;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Search extends HttpServlet {
  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {

    //検索結果格納用
    HashMap<String,String> result = new HashMap<String,String>();

    //パラメータ取得・エスケープ
    req.setCharacterEncoding("utf-8");
    String name = escapeString(req.getParameter("name"));

    try {
      //JDBC ドライバ読み込み
      Driver d = (Driver) Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();

      //SQL Server 接続文字列
      String connUrl =
                "jdbc:sqlserver://localhost:1433;database=Test;"
                  + "user=user01;password=pass";

      //DB に接続
      Connection con = d.connect(connUrl, new Properties());

      //プレースホルダで SQL 作成
      String sql = "SELECT ID,NAME FROM USERS WHERE NAME LIKE ? ESCAPE '#';";

      //SQL をプリコンパイル
      PreparedStatement pstmt = con.prepareStatement(sql);

      //パラメーターセット
      pstmt.setString(1, name);

      //SQL 実行
      ResultSet rs = pstmt.executeQuery();

      //結果格納
      while (rs.next()) {
        result.put(rs.getString("ID"), rs.getString("NAME"));
      }

      rs.close();
      pstmt.close();
      con.close();

    }
    catch (Exception e){
      e.printStackTrace();
    }

    if (result.size() > 0) {
      //検索結果をセット
      req.setAttribute("result", result);

      //検索結果画面へ
      ServletContext sc = getServletContext();
      RequestDispatcher rd = sc.getRequestDispatcher("/result.jsp");
      rd.forward(req, resp);
    } else {
      resp.sendRedirect("/test/input.jsp");
    }
  }

  private String escapeString(String name) {
    return "%" + name.replaceAll("[_%\\[#]", "#$0") + "%";
  }
}

・result.jsp

クロスサイト・スクリプティング対策の HTML エスケープ処理を行うために、Apache Commons lang 3の StringEscapeUtils#escapeHtml4 メソッドを利用します。

<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="org.apache.commons.lang3.StringEscapeUtils" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
  <h1>検索結果</h1>
<%
  HashMap<String,String> result = (HashMap<String,String>)request.getAttribute("result");

  Iterator i = result.keySet().iterator();

  while (i.hasNext()) {
    Object o = i.next();
    out.println(StringEscapeUtils.escapeHtml4(o + ":" + result.get(o)) + "<br/>");
  }
%>

</body>
</html>

参考

Webアプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。


スポンサーリンク





カテゴリー:Webアプリケーションセキュリティ対策

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA