SQL Injection공격은 무엇인가?

  SQL Injection은 웹 어플리케이션에서 DB에 Query시 입력된 데이터의 유효성 검증을 하지 않아,
개발자가 의도하지 않는 동적 쿼리(Dynamic Query) 를 생성하여 DB정보를 열람하거나 조작할 수 있는 보안 취약점 입니다.

 

SQL Injection공격은 왜 발생할까?
웹 어플리케이션은 User의 행동(클릭, 입력등)에 따라 DB에 있는 데이터를 서로 다르게 표시합니다.
이를 위해 Query는 User가 입력한 데이터를 포함하여 Dynamic하게 변하므로 개발자가 의도하지 않은 정보를 열람할 수 있게 됩니다.

 

SQL Injection공격 방어

1) 입력값 검증
사용자의 입력이 DB Query에 동적으로 영향을 주는 경우 입력된 값이 개발자가 의도한 값(요효값) 인지 검증합니다.

/*, –, ‘, “, ?, #, (, ), ;, @, =, *, +, union, select, drop, update, from, where, join, substr, user_tables, user_table_columns, information_schema, sysobject, table_schema, declare, dual,…

등과 같은 의도하지 않은 입력값에 대해 검증하고 차단해야 합니다.

 

  • 입력값 검증(JAVA) Example >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.regex.Matcher;
import java.util.regex.Pattern;

 

/* 특수문자 공백 처리 */
final Pattern SpecialChars = Pattern.compile(“[‘\”\\-#()@;=*/+]”);
UserInput = SpecialChars.matcher(UserInput).replaceAll(“”);

 

final String regex = “(union|select|from|where)”;

 

final Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
final Matcher matcher = pattern.matcher(UserInput);

 

if(matcher.find()){
    out.println(“<script>alert(‘No SQL-Injection’);</script>”);
}
cs

 

  • 입력값 검증(PHP) Example >
1
2
3
4
$UserInput = preg_replace(“/[\r\n\s\t\’\;\”\=\-\-\#\/*]+/”,“”$UserInput);
if(preg_match(‘/(union|select|from|where)/i’$UserInput)) {
    $this>Error_popup(‘No SQL-Injection’);
}
cs

 

2) 저장 프로시저 사용

저장 프로시저는 사용하자고 하는 Query에 미리 형식을 지정하는 것을 말합니다. 지정된 형식의 데이터가 아니면 Query가 실행되지 않기 때문에 보안성을 크게 향상시킵니다.

 

  • 취약 코드(JAVA) Example >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
try{
  String uId = props.getProperty(“jdbc.uId”);

 

  String query = “SELECT * FROM tb_user WHERE uId=” + uId;
  stmt = conn.prepareStatement(query);
  ResultSet rs = stmt.executeQuery();
  while(rs.next()){
    .. …
  }
}catch(SQLException se){
  .. …
}finally{
  .. …
}
cs

 

  • 안전한 코드(JAVA) Example >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try{
  String uId = props.getProperty(“jdbc.uId”);

 

  String query = “SELECT * FROM tb_user WHERE uId= ?”

 

  stmt = conn.prepareStatement(query);
  stmt.setString(1, uId);

 

  ResultSet rs = stmt.executeQuery();
  while(rs.next()){
    .. …
  }
}catch(SQLException se){
  .. …
}finally{
  .. …
}
cs

 

  • 안전한 코드(PHP) Example >
1
2
3
4
5
6
7
8
9
if(ctype_digit($_POST[‘uId’]) && is_int($_POST[‘uId’])) {
    $validateduId = $_POST[‘uId’];
    $pdo = new PDO(‘mysql:store.db’);
    $stmt = $pdo>prepare(‘SELECT * FROM tb_user WHERE user_id = :uId’);
    $stmt>bindParam(‘:uId’$validateduId, PDO::PARAM_INT);
    $stmt>execute();
else {
    // reject id value
}
cs

 

3) 서버 보안

  1. 최소 권한 유저로 DB 운영
  2. 사용하지 않는 저장 프로시저와 내장함수 제거 또는 권한 제어
  3. 목적에 따라 Query권한 수정
  4. 공용 시스템 객체의 접근 제어
  5. 신뢰할 수 있는 네트워크, 서버에 대해서만 접근 허용
  6. 에러 메시지 노출 차단