SQL Injection 공격 방지
설명 |
웹 애플리케이션에서 사용되는 SQL 구문에 공격자가 임의의 구문을 주입(Injection) 하여 내부 데이터베이스의 데이터를 유출, 변조할 수 있는 취약점이다. |
발생원인 |
웹 페이지에서 사용자로부터 입력받은 값을 제대로 검사하지 않고 그대로 데이터 질의어로 사용할 경우 발생한다. |
위험성 |
데이터 유출, 변조 외에도 서버에 파일을 쓰거나 읽을 수 있고, 직접 명령 실행도 가능할 수 있기 때문에 위험도가 높은 취약점이다. |
SQL 인젝션은 데이터베이스를 사용하는 모든 언어에서 일어날 수 있다.
공격자는 SQL 인젝션 취약점을 사용하여 데이터베이스 내의 모든 정보를 추출할 수 있다.
보통 userID 와 passwd 를 입력하는 로그인 창에서 발생할 수 있는 공격 유형이다.
select * from members where userID='$userID' and passwd ='$passwd';
여기서 userID 에 입력하는 정보를 ' or 1=1-- 라고 입력하는 것이 받아들여지면 어떤 결과가 초래될까?
phpMyAdmin 상에서 직접 테스트 해보라.
SELECT * FROM members WHERE userID='' or 1=1 --' and passwd ='abc123';
과같이 -- 주석 뒷부분은 무용지물이 되고 조건문은 무조건 참이 되어 모든 결과를 반환하게 된다.
select * from members where userID='a' and passwd ='password' OR 1='1';
로 입력해도 무조건 참이 되어 모든 결과를 반환하게 된다.
더 위험한 것은 테이블 자체를 삭제시켜 버릴 수가 있다는 점이다.
$userID = "admin"; |
공백이후 and 를 체크하지 않고 그냥 체크하면 userID 중에 hand 가 들어간 것도 필터링을 해서 문제가 될 수 있다.
그럼 여기서 안전하게 코딩하기 위한 포인트는 무엇인가?
① 필터링 메소드를 만들어서 악의적인 코드를 무조건 걸러내도록 한다.
필터링 해야 할 특수문자 : '(홀따옴표) ;(콜론), --(주석), 공백 등
https://link2me.tistory.com/1489 정규표현식 연습 참조하면 정규표현식 이해에 도움된다.정규표현식을 활용한 함수 만들기
function SQLFiltering($str){
// 해킹 공격을 대비하기 위한 코드
$str=preg_replace("/\s{1,}1\=(.*)+/","",$str); // 공백이후 1=1이 있을 경우 제거
$str=preg_replace("/\s{1,}(or|and|null|where|limit)/i"," ",$str); // 공백이후 or, and 등이 있을 경우 제거
$str = preg_replace("/[\s\t\'\;\=]+/","", $str); // 공백이나 탭 제거, 특수문자 제거
return $str;
}
② 안전한 코딩은 prepared Statement 와 바인딩 변수를 이용하도록 권고하고 있다.
Prepared Statement 를 쓰면 SQL 인젝션 공격이 불가능할 수 밖에 없다.
바인딩 데이터는 SQL 문법이 아닌 내부의 인터프리터나 컴파일 언어로 처리하기 때문에
문법적인 의미를 가질 수 없다.
$stmt = $mysqli->prepare("SELECT * FROM members WHERE userID= ? AND passwd = ?"); |
참고하면 도움이 될 게시글
ㅇ PHP Prepared Statements https://www.w3schools.com/php/php_mysql_prepared_statements.asp
ㅇ PHP Legacy 함수를 PDO 방식 함수로 변환하기 https://link2me.tistory.com/1636