2015년 11월 30일 월요일

입력데이터 검증 및 표현 - SQL 삽입 (SQL Injection)

1.  입력데이터 검증 및 표현
프로그램 입력 값에 대한 검증 누락 또는 부적절한 검증, 데이터의 잘못된 형식지정, 일관되지 않은 언어셋 사용 등으로 인해 발생하는 보안약점으로 SQL 삽입, 크로스사이트 스크립트(XSS) 등의 공격을 유발할 수 있다.

1)     SQL 삽입(SQL Injection)
데이터베이스(DB)와 연동된 웹 어플리케이션에서 입력된 데이터에 대한 유효성 검증을 하지 않을 경우, 공격자가 입력 폼 및 URL 입력란에 SQL 문을 삽입하여 DB로부터 정보를 열람하거나 조작할 수 있는 보안약점을 말한다.

n  안전한 코딩 기법
     PreparedStatement 클래스와 하위 메소드 excuteQuery(), execute(), excuteUpdate()를 사용한다.
     PreparedStatement 클래스를 사용할 수 없는 환경이라면, 입력 값을 필터링 처리한 후 사용한다.
     Mybatis Data Map 파일의 인자를 받는 질의 명령어 정의시에 문자열 삽입 인자($..$)를 사용하지 않고, 질의 구조에 영향을 주지 않는 #<인자이름># 형태의 질의문을 사용한다. 부득이하게 삽입인자($..$)를 사용할 경우에는 입력 값을 필터링 처리하여 사용한다.


  1. import java.io.IOException;  
  2. import java.sql.Connection;  
  3. import java.sql.DriverManager;  
  4. import java.sql.ResultSet;  
  5. import java.sql.SQLException;  
  6. import java.sql.Statement;  
  7. import java.util.regex.Matcher;  
  8. import java.util.regex.Pattern;  
  9.   
  10. import javax.servlet.ServletConfig;  
  11. import javax.servlet.ServletException;  
  12. import javax.servlet.http.HttpServlet;  
  13. import javax.servlet.http.HttpServletRequest;  
  14. import javax.servlet.http.HttpServletResponse;  
  15.   
  16. public class SQLInjectionSample extends HttpServlet {  
  17.     private static final long serialVersionUID = 1L;  
  18.     private Connection conn;  
  19.       
  20.     private final static int MAX_USER_ID_LENGTH = 14;  
  21.     private final static int MAX_PASSWORD_LENGTH = 16;  
  22.     private final static String UNSECURED_CHAR_REGULAR_EXPRESSION = "[^\\p{Alnum}]|select|delete|update|insert|create|alter|drop";  
  23.     private static Pattern unsecuredCharPattern = Pattern.compile(UNSECURED_CHAR_REGULAR_EXPRESSION, Pattern.CASE_INSENSITIVE);  
  24.       
  25.     public void init(ServletConfig config) throws ServletException {  
  26.         unsecuredCharPattern = Pattern.compile(UNSECURED_CHAR_REGULAR_EXPRESSION, Pattern.CASE_INSENSITIVE);  
  27.     }  
  28.       
  29.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  30.         Statement stmt = null;  
  31.         ResultSet rs = null;  
  32.         String action = request.getParameter("action");  
  33.         if(action == null || "".equals(action)) { action = "default"; }  
  34.         if(action.equals("login")) {  
  35.             try {  
  36.                 conn = DriverManager.getConnection("url""user""password");  
  37.                 stmt = conn.createStatement();  
  38.                 String userId = request.getParameter("user_id");  
  39.                 String password = request.getParameter("password");  
  40.                   
  41.                 if(userId == null || "".equals(userId) || password == null || "".equals(password)) {  
  42.                     throw new Exception("check login info");  
  43.                 } else {  
  44.                 }  
  45.                   
  46.                 userId = makeSecureString(userId, MAX_USER_ID_LENGTH);  
  47.                 password = makeSecureString(password, MAX_PASSWORD_LENGTH);  
  48.                   
  49.                 String query = "SELECT * FROM MEMBERS WHERE userid=" + userId + " AND password=" + password;  
  50.                 rs = stmt.executeQuery(query);  
  51.                   
  52.             } catch (SQLException e) {  
  53.                 System.out.println(e.getMessage());  
  54.                 e.printStackTrace();  
  55.             } catch (Exception e) {  
  56.                 System.out.println(e.getMessage());  
  57.             } finally {  
  58.                 try {  
  59.                     if(rs != null) { rs.close(); }  
  60.                     if(stmt != null) { stmt.close(); }  
  61.                     if(conn != null) { conn.close(); }  
  62.                 } catch (SQLException e) {  
  63.                     System.out.println(e.getMessage());  
  64.                 }  
  65.             }  
  66.         }  
  67.     }  
  68.       
  69.     private String makeSecureString(final String str, int maxLength) {  
  70.         String secureStr = str.substring(0, maxLength);  
  71.         Matcher matcher = unsecuredCharPattern.matcher(secureStr);  
  72.           
  73.         return matcher.replaceAll("");  
  74.     }  
  75. }  

댓글 없음:

댓글 쓰기