#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for
import socket
app = Flask(__name__)
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
@app.route('/')
def index():
return render_template('index.html')
@app.route('/socket', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('socket.html')
elif request.method == 'POST':
host = request.form.get('host')
port = request.form.get('port', type=int)
data = request.form.get('data')
retData = ""
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(3)
s.connect((host, port))
s.sendall(data.encode())
while True:
tmpData = s.recv(1024)
retData += tmpData.decode()
if not tmpData: break
except Exception as e:
return render_template('socket_result.html', data=e)
return render_template('socket_result.html', data=retData)
@app.route('/admin', methods=['POST'])
def admin():
if request.remote_addr != '127.0.0.1':
return 'Only localhost'
if request.headers.get('User-Agent') != 'Admin Browser':
return 'Only Admin Browser'
if request.headers.get('DreamhackUser') != 'admin':
return 'Only Admin'
if request.cookies.get('admin') != 'true':
return 'Admin Cookie'
if request.form.get('userid') != 'admin':
return 'Admin id'
return FLAG
app.run(host='0.0.0.0', port=8000)
문제 소스코드이다.
문제화면도 한번 봐보자.
소켓통신을 이용하는 페이지인 거 같다.
일단 이것저것 실험하는 마음으로 host, port는 넣어주고 Data는 아무거나 넣어본다.
timed out 이 출력된다.
retData = ""
try:
# 소켓 객체 생성, 타임아웃 설정 및 서버에 연결 시도
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(3)
연결하는데 3초이상 걸리면 바로 내보낸다.
애초에 소켓통신인데 Data를 저렇게 넣으면 안 되나 보다.
양식을 만들어보자.
@app.route('/admin', methods=['POST'])
def admin():
if request.remote_addr != '127.0.0.1':
return 'Only localhost'
if request.headers.get('User-Agent') != 'Admin Browser':
return 'Only Admin Browser'
if request.headers.get('DreamhackUser') != 'admin':
return 'Only Admin'
if request.cookies.get('admin') != 'true':
return 'Admin Cookie'
if request.form.get('userid') != 'admin':
return 'Admin id'
return FLAG
/admin 경로를 보면 localhost 를 확인하고 헤더인 'User-Agent' , 'DreamhackUser' , 'Cookie' 검사하며 form 인 Body 데이터 'userid'가 admin 인지 확인을 하여 모든 조건이 충족될 경우 flag를 출력해 준다.
소켓통신을 이용해서 문제를 한번 풀어보자.
일단 host를 loopback 주소로 설정하여 POST 메서드로 전달할 /admin 경로에 자기 자신인 것을 알리고
port 8000 은 소스코드에 app.run 이 8000으로 설정되어 있다. (요청 수신이 8000 포트라는 뜻)
User-Agent, Dreamhackuser, cookie는 보인 그대로 써주고
form 값인 userid는 Header와 분리되게 줄 바꿈을 해준다.
이걸 토대로 넣어주면...
Admin id 라 출력이 된다.
if request.form.get('userid') != 'admin':
return 'Admin id'
데이터가 제대로 간 게 아닌 거 같다.
뭐가 빠진 거냐면 POST 요청에서 데이터를 전송할 때 서버가 클라이언트로부터 전송받은 데이터를 어떻게 해석하고 분석할지 결정하는 역할을 하는 'Content' 헤더가 필요하다고 한다.
즉 해석과 처리방법을 알려주지 않고 데이터만 보낸 셈이다.
알맞은 Content를 설정해 주고 보내면 플래그를 발행해 준다.
'DreamHack > WEB' 카테고리의 다른 글
php-1 (1) | 2024.10.16 |
---|---|
XSS Filtering Bypass (0) | 2024.10.16 |
web-misconf-1 (1) | 2024.10.10 |
blind-command (0) | 2024.10.10 |
session (1) | 2024.10.08 |