보안 스터디/웹 해킹

[드림핵/워게임] BypassIF - WriteUp

성밍쟁 2025. 2. 16. 18:44
728x90
반응형

프롤로그

버프 스위프 사용법을 이제야 다시 확인한 기분;;

저거 안 돼서 억울해 죽을 뻔했다.

 

 

 

 

문제

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}

 이다.

 

 

에필로그

728x90
반응형