[시큐어 코딩] #1 SQL 삽입 / preparedStatement란 :: 잡다한 프로그래밍
반응형

1. Statement / preparedStatement란

#1) PreparedStatement의 동작방식

 

preparedStatement는 다음과 같이 4가지 단계로 이루어져있다. 이중 parse 부분을 컴파일한채로 캐시에 저장하고 데이터가 bind될때까지 기다린다 이후 patch부분까지 실행이 완료되고 sql을 재사용할때 parse를 다시 실행하지않고 캐시에 저장되어있는 부분을 가져다 나머지 3단계만 실행한다. 따라서 sql이 반복적일때 효율적이다.

 

또한 바인딩 된 데이터는 SQL문법이 아닌 내부의 인터프리터나 컴파일 언어로 처리하므로, 문법적인 의미를 가질 수 없다. 이것이 의미하는것은 parse부분에서 이미 쿼리의 문법적인 처리부분이 선 수행되었으므로 바인딩 단계에서 입력된 부분은 쿼리로 인식하지 않는다는 의미이다. 따라서 sql injection에 좋다.

 

사용 방법

String sql = "SELECT NAME, AGE FROM TABLE WHERE userID = ?"
PreparedStatement stmt = conn.prepareStatement(sql);
pstmt.setInt(1, userID);
ResultSet rst = pstmt.executeQuery();

 

#2) Statement의 동작방식

Statement는 prepare방식과 달리 4가지단계를 매번 실행하여 결과 값을 반환한다. 만약 반복적으로 쿼리를 수행할경우 PreparedStatement가 DB에 적은 부하를 주며, 성능이 더 좋다.

하지만 sql을 전체를 한눈에 볼 수 있다는 장점이 있다.

String sql = "SELECT NAME, AGE FROM TABLE WHERE USERID = " + userID
Statement stmt = conn.credateStatment();
ResultSet result = stmt.executeQuery(sqlstr);

 

2. SQL 삽입

사용자가 입력 폼 및 URL 입력란에 SQL을 삽입하여 DB로부터 정보를 열람하거나 조작할 수 있는 보안적 약점을 의미한다.

이를 대비하기위해 PreparedStatement를 이용하는것이 바람직하다 예를들어 다음과 같은 statement 쿼리문을 작성했다고 가정할때 사용자가 name값을 name' OR 'a' = 'a라고 입력할경우 모든 테이블이 조회가 되는 문제가 생긴다.

String query = "SELECT * FROM " + tableName + "WHERE Name = " + name;

따라서 이를 PreparedStatement(데이터 바인딩) 으로 처리하면 안전하게 SQL 삽입으로부터 대비할 수 있다. 보다 안전한 이유는 PreparedStatement를 보면 알 수 있다.

String query = "SELECT * FROM ? WHERE Name = ?";
stmt = con.prepareStatement(query);
stmt.setString(1, tableName);
stmt.setString(2, name);
rs = stmt.executeQuery();
반응형

+ Recent posts