[DreamHack] λ“œλ¦Ό 병원 🌱 풀이

μ½”λ”© νŒŒμΈμ• ν”ŒΒ·2026λ…„ 7μ›” 14일

CHALLENGE SOLVING

λͺ©λ‘ 보기
4/11
post-thumbnail

μ•ˆλ…•ν•˜μ‹­λ‹ˆκΉŒ μ½”λ”© νŒŒμΈμ• ν”Œμž…λ‹ˆλ‹€
μ΄λ²ˆμ—λŠ” λ“œλ¦Ό 병원 πŸŒ±μ— κ΄€ν•΄ ν’€μ–΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

λ“œλ¦Ό 병원 🌱

https://dreamhack.io/wargame/challenges/2814

저희 λ“œλ¦Ό 병원은 ν™˜μž 정보λ₯Ό μ•ˆμ „ν•˜κ²Œ λ³΄ν˜Έν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. πŸ₯
...

import hashlib
import os
from flask import Flask, render_template, request, redirect, url_for, session, abort

app = Flask(__name__)
app.secret_key = os.urandom(24).hex()

health_records = {
    1: {
        "name": "κΉ€κΉƒλ°œ",
        "date": "2024-03-10",
        "height": "175cm",
        "weight": "70kg",
        "blood_pressure": "120/80",
        "diagnosis": "νŠΉμ΄μ‚¬ν•­ μ—†μŒ (κ²€μ§„μ™„λ£Œ)",
        "summary": "DH{This_is_fake_flag}", #β•ν”Œλž˜κ·Έ μœ„μΉ˜
        "owner": "admin"
    },
    125: {
        "name": "κΉ€λ“œλ¦Ό",
        "date": "2024-03-25",
        "height": "180cm",
        "weight": "75kg",
        "blood_pressure": "115/75",
        "diagnosis": "비타민 D λΆ€μ‘± ꢌ고",
        "summary": "μ „λ°˜μ μœΌλ‘œ μ–‘ν˜Έν•˜λ©° κΎΈμ€€ν•œ μš΄λ™μ„ ꢌμž₯ν•©λ‹ˆλ‹€.",
        "owner": "guest"
    }
}

def get_hash(uid):
    return hashlib.md5(str(uid).encode()).hexdigest()

@app.route('/')
def index():
    if 'user' in session:
        return redirect(url_for('dashboard'))
    return render_template('index.html')

@app.route('/auth/login', methods=['POST'])
def login():
    if request.form.get('username') == 'guest' and request.form.get('password') == 'guest':
        session['user'] = 'guest'
        return redirect(url_for('dashboard'))
    return "Login Failed", 401

@app.route('/auth/logout')
def logout():
    session.pop('user', None)
    return redirect(url_for('index'))

@app.route('/dashboard')
def dashboard():
    if 'user' not in session:
        return redirect(url_for('index'))
    
    user_data = health_records[125]
    return render_template('dashboard.html', user_hash=get_hash(125), name=user_data['name'])

@app.route('/report/view/<user_hash>')
def view_report(user_hash):
    if 'user' not in session:
        return redirect(url_for('index'))
    
    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            if data['owner'] != session['user']:
                return "<h1>Access Denied</h1>", 403
            return render_template('report.html', data=data, user_hash=user_hash)
            
    return "Not Found", 404

@app.route('/report/download/<user_hash>')
def download_report(user_hash):
    if 'user' not in session:
        return redirect(url_for('index'))
    
    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            return render_template('print.html', data=data)
            
    return "Not Found", 404

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=False)

일단 guest/guestλ₯Ό 톡해 guest둜 둜그인 ν•΄λ΄…μ‹œλ‹€

음, μ½”λ“œλ₯Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€

μ½”λ“œλ₯Ό λ³΄μ‹œλ©΄ λ‹€μŒκ³Ό 같이 μ˜μ‹¬μŠ€λŸ¬μš΄ 뢀뢄이 μ‘΄μž¬ν•©λ‹ˆλ‹€

def get_hash(uid):
    return hashlib.md5(str(uid).encode()).hexdigest()
    
    
...


@app.route('/report/view/<user_hash>')
def view_report(user_hash):
    if 'user' not in session:
        return redirect(url_for('index'))
    
    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            if data['owner'] != session['user']:
                return "<h1>Access Denied</h1>", 403
            return render_template('report.html', data=data, user_hash=user_hash)
            
    return "Not Found", 404

μ΄λ ‡κ²Œ λ‹€μŒκ³Ό 같이 uidλ₯Ό λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•œ λ’€ MD5 μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ ν•΄μ‹±ν•˜κ³ , κ·Έ κ²°κ³Όλ₯Ό 16μ§„μˆ˜ λ¬Έμžμ—΄λ‘œ λ°˜ν™˜ν•˜λŠ” ꡬ문을 url에 λ„£μ–΄ IDOR이 κ°€λŠ₯함을 μœ μΆ”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

report/view/3def184ad8f4755ff269862ea77393dd

guest둜 λ‘œκ·ΈμΈν•˜μ‹œλ©΄ url이 λ‹€μŒκ³Ό 같이 λ‚˜μ˜€λŠ” 것을 μ•Œ 수 있으며 μ΄λŠ” 125의(health_record의 guest번호) get_hash() κ°’μž„μ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€

λ”°λΌμ„œ μ €ν¬λŠ” ownerκ°€ admin의 λ²ˆν˜Έκ°€ λ˜λŠ” 1을 get_hash()에 λ„£μ–΄ IDORλ₯Ό μ‹œλ„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ 이걸 κ³§μ΄κ³§λŒ€λ‘œ /report/view/<user_hash> 에 λ„£κ²Œ 되면 μ½”λ“œμ²˜λŸΌ 'Access Denied'κ°€ λ‚˜μ˜€κ²Œ λ©λ‹ˆλ‹€

κ²°κ³Όν‘œκ°€ λ˜λŠ” /report/download/<user_hash> λŠ” μ’€ λ‹€λ₯Έ κ²°κ³Όκ°€ λ‚˜μ˜΅λ‹ˆλ‹€

@app.route('/report/download/<user_hash>')
def download_report(user_hash):
    if 'user' not in session:
        return redirect(url_for('index'))
    
    for uid, data in health_records.items():
        if get_hash(uid) == user_hash:
            return render_template('print.html', data=data)
            
    return "Not Found", 404

/report/view/<user_hash>μ™€λŠ” λ‹€λ₯΄κ²Œ 둜그인 확인 ν›„, 찾은 λ°μ΄ν„°μ˜ 주인과 ν˜„μž¬ λ‘œκ·ΈμΈν•œ μ‚¬μš©μžκ°€ μΌμΉ˜ν•˜λŠ”μ§€ λΉ„κ΅ν•˜μ§€ μ•ŠκΈ°μ—
(data['owner'] != session['user'])

/report/view/c4ca4238a0b923820dcc509a6f75849b
을 톡해 μ ‘κ·Όν•˜λ©΄ ν”Œλž˜κ·Έλ₯Ό νšλ“ν•  수 있게 λ©λ‹ˆλ‹€.

FLAG :

평가 :

profile
PINEAPPELπŸ—£οΈπŸ”₯πŸ”₯πŸ”₯πŸ”₯

0개의 λŒ“κΈ€