ProxyAsService
Autore: Lord Shiva • Aggiornamento: 08.12.2023 • Tempo di lettura: 05 min.Prima di tutto, scarico i file zip per analizzare il codice.
Come possiamo vedere, la flag viene inserita in una variabile di ambiente.
# Place flag in environ
ENV FLAG=HTB{f4k3_fl4g_f0r_t3st1ng}
Nel file routes.py il parametro URL viene convalidato se non è vuoto e lo statico SITE_NAME viene aggiunto prima di eseguire una richiesta a questo URL. L'applicazione si aspetta che un utente inserisca un subreddit come "/r/cybersecurity".
from application.util import is_from_localhost, proxy_req
import random, os
SITE_NAME = 'reddit.com'
proxy_api = Blueprint('proxy_api', __name__)
debug = Blueprint('debug', __name__)
@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())
@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)
Esiste una directory /debug/environmentroute che restituisce le variabili di ambiente, solo quando il parametro URL è un URL locale.
@is_from_localhost
def debug_environment():
environment_info = {
'Environment variables': dict(os.environ),
'Request headers': dict(request.headers)
}
return jsonify(environment_info)
Analizzando il file util.py esiste una lista nera che impedisce al proxy di fornire URL locali per prevenire attacchi di falsificazione di richieste lato server.
def is_safe_url(url):
for restricted_url in RESTRICTED_URLS:
if restricted_url in url:
return False
return True
def is_from_localhost(func):
@functools.wraps(func)
def check_ip(*args, **kwargs):
if request.remote_addr != '127.0.0.1':
return abort(403)
return func(*args, **kwargs)
return check_ip
Per acquisire la flag, dobbiamo superare due sfide:
La prima sfida è il metodo di convalida noto come is_from_localhost. Questo controllo è progettato per verificare se l'URL fornito è locale. Aggirarlo non è eccessivamente complesso poiché le liste negate sono spesso incomplete. Esistono numerose tecniche di bypass ed è possibile trovare un elenco completo degli hacktrick. Ad esempio, un esempio potrebbe essere http://0.0.0.0/.
La seconda sfida richiede un po’ più di creatività. Esistono almeno due strategie per affrontarlo. Noi utilizziamo la prima soluzione, lasciando quella un pò più complessa per un'altra volta:
Soluzione 1: utilizzare il simbolo “@”.
Un approccio consiste nello sfruttare la presenza del simbolo “@” all'interno di un URL per l'autenticazione. Inserendo il simbolo “@” nell'URL, il server può interpretare tutto ciò che precede il simbolo “@” come credenziali di autenticazione e ignorarlo, ottenendo così il controllo sull'intero URL.
URL di attacco: http://<ip_target>/?url=@0.0.0.0:1337/debug/environment
In caso di sfruttamento riuscito, avrai accesso alle variabili di ambiente, che potrebbero includere l'ambita bandiera: HTB{fl4g...........1c3}