프롤로그
버프 스위프 사용법을 이제야 다시 확인한 기분;;
저거 안 돼서 억울해 죽을 뻔했다.
문제
https://dreamhack.io/wargame/challenges/1151
BypassIF
Description Admin의 KEY가 필요합니다! 알맞은 KEY값을 입력하여 플래그를 획득하세요. 플래그 형식은 DH{...} 입니다.
dreamhack.io
코드 및 분석
app = Flask(__name__)
try:
FLAG = open("./flag.txt", "r").read()
except:
FLAG = "[**FLAG**]"
일단 flag.txt로부터 파일을 읽고 해당 내용을 FLAG 라는 변수에 저장한다.
KEY = hashlib.md5(FLAG.encode()).hexdigest()
guest_key = hashlib.md5(b"guest").hexdigest()
그리고 KEY는 FLAG를 md5 해쉬함수로 암호화 한 것이고
guest_key는 guest라는 단어를 암호화한것이다.
md5가 보이는데
MD5(Message Digest Algorithm 5)는 입력 데이터를 128비트(16바이트) 길이의 고정된 해시 값으로 변환하는 암호화 해시 함수이다.
@app.route('/', methods=['GET', 'POST'])
def index():
# GET request
return render_template('index.html')
/ 경로에 가게 되면 그냥 Index.html로 넘어가라고 나온다.
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
<h1>hello dream</h1>
<form action="/flag" method="POST">
<div class="row">
<div class="col-md-6 form-group">
<br/><input type="text" class="form-control" placeholder="your key" name="key" pattern="[A-Za-z0-9\s]{2,35}" required>
</div>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<br/><br/>
{% if txt %}
<pre>{{ txt }}</pre>
{% endif %}
{% endblock %}
index.html은
/flag로 넘어가는 것이 있다. key을 여기서 입력을 하고 Submit 버튼 제출을 하면, 해당 데이터가 넘어가진다.
그리고 txt가 있다면 출력을 해준다.
저 txt가 나중에 FLAG가 나올 자리이다.
@app.route('/flag', methods=['POST'])
def flag():
# POST request
if request.method == 'POST':
key = request.form.get('key', '')
cmd = request.form.get('cmd_input', '')
if cmd == '' and key == KEY:
return render_template('flag.html', txt=FLAG)
elif cmd == '' and key == guest_key:
return render_template('guest.html', txt=f"guest key: {guest_key}")
if cmd != '' or key == KEY:
if not filter_cmd(cmd):
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('flag.html', txt=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
except subprocess.CalledProcessError:
return render_template('flag.html', txt="Error!")
return render_template('flag.html')
else:
return redirect('/')
else:
return render_template('flag.html')
flag를 가면
일단 GET요청이라면? 그냥 바로 다시 index.html로 넘어가진다. 바로 다이렉트로 해당 링크로는 들어갈 수가 없다는 것을 의미한다.
POST 요청일 떄를 봐야하는데
폼에서부터 key, cmd_input을 입력받는데,
cmd가 비어있는데 KEY가 맞다면 flag.html로 보내버리고,
cmd가 비어있는데 키가 게스트키라면 guest.html로 보내버린다.
그리고 cmd키가 비어있지않거나, admin 키라면?
cmd를 필터를 걸쳐서 제대로 통과한다면, 명령을 수행하게 된다.
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('flag.html', txt=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
정상적으로 수행이 되었을 떄 웹 셸과 같은 기능을수행하는 거 같은데
타임오류가 발생하면 뜬금없이 키 값을 알려주는 코드가 있다.
풀이전략
if cmd != '' or key == KEY:
or로 적혀있다.
키값이 뭐가되었던 간에, cmd로 timeout 걸리게 만들어놓고(sleep(10)) , 그러면 timeout이 걸려서 키 값을 반환해줄 것이다.
그 키 값을 가지고서 입력하면 플래그가 나올 것이다.
풀이과정
일단 guest_key값을 한 번 알아보자.
import os
import hashlib
guest_key = hashlib.md5(b"guest").hexdigest()
print(guest_key)
이렇게 코드 짜고 수행하면
guest 키 값이 나온다.
음, 키 값 입력해서 아마 넘어온 곳이 guest.html인 것 같다.
일단, burp suite를 켜서 key는 아무거나 넣어주고 cmd값이라도 추가해서 보내주자.
이렇게 했더니 ls가 나왔다.
아까 풀이전략에서 말했듯이 대충 타임아웃 5초 지나면 키 값이 나올테니까, sleep(5)를 해보자.
했는데 안 되네;;
아 안 되는 이유가
sleep(5) 가 아니라 sleep 5 로 해야한다.
저렇게 설정하고 하면
키 값이 나온다.
저게 어드민 키일테니까 저걸로 이제 들어가보자.
입력하는 곳에다가
저 키값 입력하면
플래그가 나온다.
FLAG
플래그는
DH{9c73a5122e06f1f7a245dbe628ba96ba68a8317de36dba45f1373a3b9a631b92}
이다.
에필로그
아
'보안 스터디 > 웹 해킹' 카테고리의 다른 글
[드림핵/워게임] login-1 - WriteUp (0) | 2025.02.28 |
---|---|
[드림핵/워게임] XSS Filtering Bypass Advanced - WriteUp (1) | 2025.02.17 |
[드림핵/워게임] baby-jwt - WriteUp (1) | 2025.02.15 |
[드림핵/워게임] Base64 based - WriteUp (0) | 2025.02.14 |
[드림핵/워게임] File Vulnerability Advanced for linux - WriteUp (0) | 2025.02.13 |