[Dreamhack Web - Lv 2] login-1

문제 정보

python으로 작성된 로그인 기능을 가진 서비스입니다.

“admin” 권한을 가진 사용자로 로그인하여 플래그를 획득하세요.

풀이 힌트

1. Bruteforce

문제 풀이

더보기
더보기

이번 문제도 로그인 기능만 있는 것으로 보인다.

 

하지만 내 예상과는 다르게 회원가입 기능과 패스워드 찾기 기능이 있었다.

 

공격 백터를 파악하기 위해 회원가입 기능과 패스워드 찾기 기능을 살펴봤다.
특이한 점은 패스워드 찾기에서 backupCode라는 입력값이 무슨 역활을 하는지 모르겠다.

 

어떤 기능으로 이루어졌는지 확인하기 위해 회원가입 후 로그인과 패스워드 찾기를 한번씩 해보겠다.

 

test 계정을 생성하니, BackupCode를 얻을 수 있었다.

 

 test 계정으로 로그인하니, 오른쪽 상단에 test 계정의 정보가 간단하게 나타있었다.

 

오른쪽 상단의 정보 중 ID 정보은 a태그로 /uset/17로 이동하도록 되어 있었다.

 

/user/<Index> 를 넣어서 서버에 요청하니, 다른 사용자의 정보를 획득할 수 있었다.
이 기능을 통해 admin Level를 가진 계정을 찾을 수 있을거라 생각이 들었다.

 

예시로 1번 User인 Apple의 UserLevel은 1로 되어있으며 test의 UserLevel은 0으로 되어있는 것을 UserLevel 1이 admin이라는 것을 충분히 추측할 수 있다.

 

이제 패스워드 찾기 기능을 알아보기 위해 한번 시도해봤다.

 

backupCode를 맞게 넣으면 패스워드가 수정이 되는 것으로 보였다. 

 

Apple 계정을 이용하여 일부러 틀려보니 4번의 기회가 남았다는 글을 볼 수 있었다.
특이한 점은 카운트를 보여주는 사이트가 몇 초 느리게 출력된다는 것이다. 몇 번을 시도해도 계속 로딩이 걸렸다.

여기까지 확인한 결과 만약 BackupCode은 숫자로 이루어져 있으며, ID와 BackupCode를 알면 패스워드를 변경이 가능하다는 것이다. 또한 특이한 점은 카운트 페이지가 출력되는데 1~2초 정도 로딩이 걸린다는 것이다.

 

정리하고 보니 파이썬으로 한번에 여러 개의 요청을 보내면 변경할 수 있지 않을까?라는 생각을 하게 되었다.

 

import threading, requests

url = "http://host1.dreamhack.games:14828/forgot_password"


def forgot(backupCode):
    data = {"userid": "Apple", "newpassword": "Apple", "backupCode": backupCode}
    requests.post(url, data=data)
    print(f"{backupCode}번째 요청")


if __name__ == "__main__":
    threads = []
    for i in range(1, 100 + 1):
        t = threading.Thread(target=forgot, args=[i])
        t.start()
        threads.append(t)

    for thread in threads:
        thread.join()

    print("END")

위 코드는 멀티 스레드로 요청을 보내는 코드이다. 이를 이용하여 1부터 100까지의 BackupCode을 넣어서 한번에 요청을 보냈다.

멀티 스레드 설명 : https://monkey3199.github.io/develop/python/2018/12/04/python-pararrel.html

 

Apple / Apple로 로그인을 시도하니 로그인에 성공하였다. guest level에서 못 보던 admin이 보였다.

 

admin 페이지에 들어가서 확인하니, Flag가 출력되는 것을 볼 수 있었다.