프롤로그
학회 때문에 바빠죽겠는데 할 건 해야지..
문제
https://dreamhack.io/wargame/challenges/931
드림이는 바보야..
코드
#!/usr/bin/python3
from flask import Flask, request, render_template
import string
import random
app = Flask(__name__)
try:
FLAG = open("./flag.txt", "r").read() # flag is here!
except:
FLAG = "[**FLAG**]"
rand_str = ""
alphanumeric = string.ascii_lowercase + string.digits
for i in range(4):
rand_str += str(random.choice(alphanumeric))
rand_num = random.randint(100, 200)
@app.route("/", methods = ["GET", "POST"])
def index():
if request.method == "GET":
return render_template("index.html")
else:
locker_num = request.form.get("locker_num", "")
password = request.form.get("password", "")
if locker_num != "" and rand_str[0:len(locker_num)] == locker_num:
if locker_num == rand_str and password == str(rand_num):
return render_template("index.html", result = "FLAG:" + FLAG)
return render_template("index.html", result = "Good")
else:
return render_template("index.html", result = "Wrong!")
app.run(host="0.0.0.0", port=8000)
코드 분석
우선 POST 요청을 받을 때 locker_num와 password를 입력받는다.
그 다음 핵심인 코드가
if locker_num != "" and rand_str[0:len(locker_num)] == locker_num:
if locker_num == rand_str and password == str(rand_num):
return render_template("index.html", result = "FLAG:" + FLAG)
return render_template("index.html", result = "Good")
이 부분.
만약, locker_num이 비어있지 않고, 비밀번호와 locker_num이 같다, 그리고 여기서 비밀번호 까지 같으면 그때 FLAG 출력
아이디만 같다면? Good을 출력한다.
다만
if locker_num != "" and rand_str[0:len(locker_num)] == locker_num:
이 부분을 잘 봐보자.'rand_str[0:len(locker_num)] == locker_num
즉
이 부분이 내가 만약에 locker_num을 한 글자만 입력했다면, 기존에 생성된 랜덤 문자열 한 글자만 비교를 하게 되는 것이다.
풀이전략
이걸 보자마자 가장 먼저 떠오른 것은 브루트포스를 떠올렸다. 무차별 대입으로 한다고 했을 떄 저기 rand_str[0:len(locker_num)]을 보지못한상태로 브루트포스르 한다고 생각을 하면...경우의 수가
a~z 0~9까지 36의 경우의수
비밀번호는 4자리고, 숫자는 총 100개의 경우의수가 있으니까...다 곱한다면
36*36*36*36+100 =1,679,716
희망약 1백 6십만 정도의 경우의 수가 나온다. 저러면 서버 터진다.
다만 저
if locker_num != "" and rand_str[0:len(locker_num)] == locker_num:
이 한 줄로 인하여 한 문자씩 비교가 가능하여 경우의 수는 확 줄어들게 된다.
예를 들어서 맨 앞글자 36번 브루트포스하여 맨 앞글자를 알아내었으면, 두 번째 글자를 알아내기 위해서 첫번째 글자를 앞에두고 두 번쨰 글자만 브루트 포스만 돌리는 것이다.
그럼 경우의 수는 36+36+36+36+100=244 으로 확 줄어든다.
이 방법까진 알았는데, 내가 파이썬 requests 모듈로 코드를 직접짜는건가, burp suite를 사용하는 방법 없나 이때 찾아보기 시작하였고, 그래서 이번에는 burp suite를 사용해보기로 하였다. (근데 사실 requests모듈도 써본적은 없음)
풀이 과정
우선 프록시 설정을 먼저 해준다.
그 다음 burp suite로 intercept한다
그 다음 command+i (컨트롤 + i)를 누르면 저게 intruder로 가지는데, 저기서 이제 작업을 한다.
들어오면 이 페이지가 보이는데, 맨 밑 body 부분에 locker_num = test&password=이 부분에다가 이제 장난질좀 칠 것이다.
오른쪽에 ADD버튼을 이와 같이 입력하고
그 다음payloads에 가서
payload type을 브루트 포스로, 그리고 min length, max length 모두 1로 설정해준다 그다음, settings에 가서
Grep-Match 에다가, 우리가 아이디를 잘 입력했다면 Good이 뜰것이므로 추가해주고 start 버튼을 눌러준다
첫번째 비밀번호인 것에 Good 칼럼 부분에 1이 뜰것이다. 내 첫번째 비밀번호는 9였다
그 다음
방금 나온 비밀번호 9를 입력한다음에 방금과 같은 과정을 반복한다
두번째는 0
이렇게 다 구하고 나니
나의 locker_num는 90og가 나왔다. 이제 password 를 구해보자.
add로 똑같이 password 부분에 $$ 표시 해두고
이 payload 부분 브루트포스가 아닌 numbers로 100~200까지 설정하고
위와 같이 이번엔 DH로 나오는 것을 잡아야하니 저렇게 설정해두고 돌리면
162에서 값이 나온다. 즉 비밀번호는 162
이제 아까 나온 아이디와 비밀번호를 입력하면
플래그 값이 나온다
에필로그
버프수트를 좀 잘 활용해볼 수 있던 시간이었다. 브루트포스를 떠올렸다는 것에만 만족하면서, 좀 버프수트를 자주 이용하도록 해봐야겠다.
'보안 스터디 > 웹 해킹' 카테고리의 다른 글
[webhacking.kr] old-26 문제 풀이 (2) | 2024.10.01 |
---|---|
[드림핵/워게임] [wargame.kr] tmitter (웹 해킹) (1) | 2024.09.28 |
[드림핵/워게임] baby-union (웹 해킹) (9) | 2024.09.25 |
[드림핵/워게임] what-is-my-ip (웹 해킹) (3) | 2024.09.22 |
[드림핵/워게임][wargame.kr] login filtering (웹해킹) (2) | 2024.09.20 |