지금까지 SQL Injection의 개념과 다양한 공격 방법에 대해 알아보았다. SQL Injection 취약점은 데이터 유출로 이어지므로, 이를 막기 위한 대응 방안이 필요하다.
Q) 왜 발생하는가?
SQL injection이 가능한 이유는 결국 사용자가 입력한 값을 그대로 SQL 구문에 포함하기 때문이다.
따라서 SQL Injection에 대응하기 위해서는 사용자의 입력 값을 한번 검사할 필요가 있다.
① Prepared Statement
prepared statement 혹은 parameterized statement는 SQL 구문을 먼저 컴파일한 이후에 사용자의 입력값을 바인딩하는 방식을 사용한다. 특정 값을 지정하지 않은 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 방식을 우선적으로 사용하되 특정 문자만을 받는 필터링 방식(옵션으로 선택지를 정해주는)을 함께 사용하는 것이 바람직하다.
'WEB HACKING > 웹 해킹[이론]' 카테고리의 다른 글
XSS : Cross-Site Scripting 대응 방안 (0) | 2021.11.25 |
---|---|
XSS : Cross-Site Scripting (0) | 2021.11.15 |
SQL Injection : Blind SQL Injection (0) | 2021.11.05 |
SQL Injection : Error Based SQL Injection (0) | 2021.11.04 |
SQL Injection : Union SQL Injection (0) | 2021.10.28 |
댓글