TL;DR#
- 취약점: (어디서 무엇이 터지나 — 한 줄)
- 핵심 트릭: (이 문제만의 급소/함정 — 다시 볼 때 가장 먼저 떠올릴 한 줄)
- 페이로드:
(최종 한 방)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| try:
FLAG = open("./flag.txt", "r").read() # Flag is here!!
@app.route("/img_viewer", methods=["GET", "POST"])
def img_viewer():
if request.method == "GET":
return render_template("img_viewer.html")
elif 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)
|
- 항상 flag read/반환은 안 함 → 이 flag를 어떻게 내가 읽어낼 것인지가 이 문제의 핵심
- 만약 /~처럼 상대경로로 접근 → localhost:8000 + url
- 만약 localhost 입력 시도 -> 에러페이지 반환
- try~: 접근해서 컨텐츠 가져온 뒤 render_template으로 반환
취약점#
- (단계)
- (단계) ← 필요할 때만 끝에 한 줄 당위
- (단계)
함정: (당연히 먼저 해볼 법한데 막힌 것 → 왜 실패 → 어떻게 전환. 12줄. 없으면 “—”)
핵심 당위: (이 공격이 성립하는 단 하나의 이유. 12줄. 당위는 여기로 모은다.)
배운 점#