본문 바로가기
WEB HACKING/웹 해킹[이론]

SQL Injection 대응 방법

by madevth 2021. 11. 12.
반응형

지금까지 SQL Injection의 개념과 다양한 공격 방법에 대해 알아보았다. SQL Injection 취약점은 데이터 유출로 이어지므로, 이를 막기 위한 대응 방안이 필요하다.

 

Q) 왜 발생하는가?

SQL injection이 가능한 이유는 결국 사용자가 입력한 값을 그대로 SQL 구문에 포함하기 때문이다.

따라서 SQL Injection에 대응하기 위해서는 사용자의 입력 값을 한번 검사할 필요가 있다.

 

 

① Prepared Statement

prepared statement 혹은 parameterized statementSQL 구문을 먼저 컴파일한 이후에 사용자의 입력값을 바인딩하는 방식을 사용한다. 특정 값을 지정하지 않은 SQL 구문을 하나의 템플릿으로 만들어둔 후, 실행할 때 변수에 값을 지정하여 사용자가 입력한 값이 SQL 구문의 일부가 아닌 하나의 문자열로 인식되도록 한다.

 

기존의 회원가입 코드를 살펴보면, 위와 같이 변수를 받은 후 그대로 SQL 구문으로 넣어 주었다. 여기에 Prepared Statement를 적용해보자.

prepared statement는 prepare로 SQL 구문에서 변수 부분을 ‘?’로 두고 준비한 후 bind_param을 통해 변수를 바인딩한다. 첫 번째 인자 “ss”는 데이터의 타입이 string 임을 의미한다. 그 후, execute()를 통해 실행해 주면, prepared statement를 통한 SQL 구문 실행이 가능하다.

 

 

② Filtering

Filtering은 사용자의 입력 값에 특정 값이 포함되었는지를 확인하는 방식이다.

특정 문자를 포함하는 Input 값을 막거나, 특정 문자를 포함하는 Input 값만을 받는 경우로 나눌 수 있다.

SQLi에 대응하는 필터링 함수 중 두 가지를 알아보자.

 

1) mysqli_real_escape_string

mysqli_real_escape_string은 인자로 들어온 string에서 SQLi 공격과 관련된 기호를 문자로 바꾸는 함수이다. 따라서 사용자가 입력한 값이 SQL 구문의 일부가 아닌 하나의 문자열로 인식하게 만들 수 있다.

POST로 받은 값을 mysqli_real_escape_string 함수를 거친 후 SQL 구문에 넣어주면 SQLi 공격에 대응할 수 있다.

 

2) preg_match

preg_match는 사용자의 입력값으로 특정 문자열을 사용하지 못하도록 막는 함수이다. 첫 번째 인자에 막고 싶은 문자들을 넣고, 두 번째 인자에 변수를 받아 해당 문자가 있는지 검사하는 기능을 가진다.

위와 같이 작성하면 POST로 받은 값에 온점(.)이나 작은따옴표(‘)가 들어가는 경우 exit이 실행된다.

 

위의 두 가지 외에도, ' 앞에 슬래쉬를 넣는 addslashes() 등의 함수도 있지만, 특정 문자를 막는 방식은 모든 경우의 수를 방어할 수 없기 때문에 우회의 위험이 언제나 존재한다. 또한 SQLi 공격 의도로 작성하지 않은 문자도 막힐 가능성이 있으므로 한계가 존재한다.

 

 

Prepared Statement는 SQLi 공격을 원천적으로 차단하기 때문에 강력한 대응방법이 될 수 있는 반면, 정렬하는 곳 또는 테이블 이름 넣는 곳에서는 사용할 수 없기 때문에, Prepared Statement 방식을 우선적으로 사용하되 특정 문자만을 받는 필터링 방식(옵션으로 선택지를 정해주는)을 함께 사용하는 것이 바람직하다.

반응형

댓글