概要
SQL インジェクションは、プレースホルダを利用することで対策が可能ですが、Like 句のワイルドカードついては、ほとんどの情報元が「別途エスケープが必要です」としか記載されていません。
この記事では、SQL Server に対するワイルドカードのエスケープ方法の、Java の具体的例を紹介します。動作確認環境は、JDK 6 + Tomcat 7 + SQL Server 2012 です。
JDK が 6 なのは、SQL Server の JDBC ドライバが、まだ JDK 7 をサポートしていないためです。
サンプルアプリケーションの概要は、以下の通りです。
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アプリケーションセキュリティに関する記事は、以下のページにまとまっています。ぜひご確認ください。
コメント