SQL 인젝션은 코드 인젝션의 한 기법으로 임의의 SQL 문을 주입하고 실행되게 하여
데이터베이스가 비정상적인 동작을 하도록 조작하는 공격방식을 말한다
인증 우회
ID, password를 입력하는 페이지를 타겟으로 하는 공격으로
정상적인 계정정보 없이 인증을 통과할 수 있다
주로 쿼리의 필터링 조건의 논리를 True로 만들어 쿼리를 무력화 하는 방법을 사용한다
DB 조작
타겟 시스템의 주요 데이터를 탈취하기 위한 방식
조작된 쿼리가 실행되도록 하여, 기업의 개인정보나 기밀정보에 접근하여 데이터를 획득할수 있다
또한 데이터 값을 변경하거나 심지어 테이블을 몽땅 지워버릴 수도 있다
DB 내부 값 유출
실질적인 injection공격을 수행하기 전 타겟 시스템의 DB명, 테이블명, 컬럼명 등의
공격포인트로 사용될 정보를 획득하기 위한 공격이다
인증 우회를 위한 패턴으로는 쿼리의 결과를 무조건 참으로 만드는 패턴을 사용한다
아래와 같은 쿼리를 사용하는 DAO에
SELECT * FROM user_table WHERE id='아이디' AND password='패스워드';
{
id="",
password=" OR '1' = '1"
}
위와 같은 입력을 주입한다면 다음과 같은 쿼리가 수행된다
SELECT * FROM users WHERE username='' and password='' OR '1'='1'
이 때 OR 조건의 오른쪽은 무조건 1이므로 WHERE문을 무시하고 쿼리가 동작하게 된다
DB 조작을 위해서 정상적인 쿼리를 중단시키고 다른 쿼리를 주입하는 패턴을 사용한다
{
id="; DELETE From Users -- And Password=''",
password=""
}
인증 우회의 경우와 같은 DAO에 위와 같은 입력을 주입하면 다음과 같은 쿼리가 수행된다
Select * From Users Where UserID = 'admin';
DELETE From Users -- And Password=''
이 때 정상 쿼리의 뒷부분은 ' -- ' 으로 인하여 주석처리 되어 실행되지 않아
주입된 쿼리가 실행되게 된다
에러메시지가 클라이언트로 전달되는 환경에서 사용되는 일반적인 injection과
에러메시지가 전달되지 않는 환경에서 사용되는 blind injection이 있다
Error Based injection
Group By와 Having 구문을 사용하여 에러를 유발시키고 그 에러 메시지로
테이블명, 다른 컬럼명을 획득한다
Union Based injection
Order By를 이용하여 대상 테이블이 몇개의 컬럼을 갖는지 등을 노출시킨다
Boolean Based injection (Blind)
쿼리 결과의 참/거짓으로부터 DB값을 유출한다
Time Based injection (Blind)
시간을 지연시키는 쿼리를 주입하여 응답 시간의 차이로 참/거짓 여부를 판별한다
prepared statement
Prepared statement를 사용하면 사용자의 입력이 쿼리문으로부터
분리되기 때문에 SQL 삽입을 효과적으로 방어할 수 있다
// 아래 쿼리에 대해서 prepared statement를 적용하면
SELECT * FROM user_table WHERE id='아이디' AND password='패스워드';
// 다음과 같이 사용할 수 있다
SELECT * FROM user_table WHERE id='%s' AND password='%s';
prepared statement 를 사용할 경우 플레이스홀더 %s를 통해 전송되는
입력값은 단순 스트링으로 처리되어 injection을 방어할 수 있다
에러 메시지 핸들
DB에서 발생하는 에러메시지가 클라이언트단에 전송될 경우 에러메시지를 통해
DB 내부 값을 획득하는 Error Based injection, Union Based injection등의
공격에 취약해 질 수 있으므로 DB의 에러메시지가 서버를 넘어가지 않도록 해야 한다
가장 간단한 방법으로 입력값으로 따옴표를 입력해보는 방법이 있다
만약 '입력에서 DB에러가 전파된다면 SQL injection에 취약한 포인트이다