[SecCon débutants CTF 2024] Rédaction Web

Ce n'était pas un très bon résultat, mais j'ai participé au CTF 2024 des débutants de Seccon, donc je vais laisser un rédaction en tant que mémo.

table des matières

ssrforfi

Vérifier la source

La structure du dossier après dézipper Tar.gz est la suivante:

$ trouver ./ ./ ./docker-compose.yml ./.env ./app ./app/app.py ./app/requiments.txt ./app/dockerfile ./app/uwsgi.ini ./nginx ./nginx/dockerfile ./nginx/nginx.conf.

Le contenu de chaque fichier est le suivant:

Services: uwsgi: build: ./app Env_file: - .env exposer: - "7777" Redémarrer: toujours nginx: build: ./nginx liens: - UWSGI PORTS: - "4989: 80" Environnement: TZ: "Asia / Tokyo" Restart: toujours
Copy nginx.conf /etc/nginx/nginx.conf cmd ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"] 
utilisateur nginx; Worker_Processes 1; error_log /var/log/nginx/error.log Warn; pid /var/run/nginx.pid; Événements {Worker_Connections 1024; } http {include /etc/nginx/mime.types; Default_type Application / Octet-Stream; LOG_FORMAT MAIN '$ Remote_addr - $ Remote_User [$ time_local] "$ request"' '$ status $ body_bytes_sent "$ http_referrer"' "$ http_user_agent" "$ http_x_forwarded_for" '; Access_log /var/log/nginx/access.log main; SendFile sur; keepalive_timeout 65; uwsgi en amont {serveur uwsgi: 7777; } Server {écouter 80; Merge_slashes off; Emplacement / {inclue uwsgi_params; uwsgi_pass uwsgi; }}}
Depuis Ubuntu: 22.04 env depian_fronttend non interactif run apt-get -y mise à jour - fixe-missing && apt-get -y mise à niveau run apt-get -y install python3 python3-pip curl run mkdir / var / www workdir / var / www copy ./. / var / www run addUser -U 1000 ssrforlfi utilisateur ssrforlfi cmd ["uwsgi", "- in", "/var/www/uwsgi.ini"]  
FLASK == 3.0.0 UWSGI == 2.0.23
[uwsgi] wsgi-file = app.py callable = app maître = true processes = 4 threads = 4 socket =: 7777 chmod-socket = 666 vide = true die-onter = true py-utoreload = 1 
Importer OS Import re Importer le sous-processus depuis FLASK Importer Flask, request app = flask (__ name__) @ app.Route ("/") def ssrforlfi (): url = request.args.get ("url") sinon URL: renvoyez "bienvenue à la vue de site Web.<br> <code>?url=http://example.com/</code> "# autoriser uniquement az,", (,),., / ,:,;, <,>, @, | Si pas re.match ('^ [az "() ./:; <> @ |] * $', url): renvoie" URL non valide; ("# ssrf & lfi Protection if url.startswith (" http: // ") ou url.startswith (" https: // "): if" localhost "dans url: return" ssrf; ("eflif url.startswith ("fichier: //"): path = url [7:] if os.path.exists (path) ou ".." dans le chemin: return "détecté lfi; (" else: # bloquer les autres schémas return "invalide scheme; (" try: # rce? proc = subprocess.run (f "curl '{url}" ",", capture_output = true = true = tex timeout = 1,) sauf sub-process.TimeoutExpired: return "timeout; (" if proc.returncode! = 0: return "error; (" return proc.stdout if __name__ == "__main__": app.run (debug = true, host = "0.0.0.0", port = 4989)

répondre

Que fait l'application est une application qui fait une demande à l'URL spécifiée par le paramètre URL "? Url = xxx" et renvoie le contenu en réponse.

Le contenu est très simple, mais j'ai dû percer les protections de SSRF et LFI et d'obtenir le drapeau.

La première chose à noter est le code ci-dessous.
HTTP et HTTPS valident localhost. Cependant, le fichier ne valide pas LocalHost.

# Ssrf & lfi protection if url.startswith ("http: //") ou url.startswith ("https: //"): if "localhost" dans url: return "détecté ssrf; (" elif url.startswith ("fichier: //"): path = url [7:] if Os.path.exists (path) ou "dans" dans le chemin: discours:] if os.path.exists (chemin) ou "dans" dans le chemin: Deth:] If Os.path.Exists (Path) ou "dans" dans le chemin: Dethe Lfi; ("Else: # Bloc d'autres schémas renvoient" Schéma non valide; ("

Le schéma de fichier: // peut accéder aux fichiers locaux, il peut donc être possible de lire les variables d'environnement, etc.
En d'autres termes, il semble que vous puissiez obtenir l'indicateur si possible ? Url = fichier: // localhost / [fichier où vous pouvez vérifier les variables d'environnement]

Cela signifie que
les variables d'environnement pour le processus actuel / proc / self / Environ Enfin, je vais l'essayer avec ? Url = file: // localhost / proc / self / environnement

Maintenant, vous obtenez le drapeau.

Je pensais que c'était quelque chose à faire de la commande d'injection, mais je n'ai pas pu résoudre le problème dans le délai.

Laveur

Requête

Partagez si vous le souhaitez!

Qui a écrit cet article

Ceci est un blog que j'ai commencé à étudier la sécurité de l'information. En tant que nouvel employé, je serais heureux si vous pouviez regarder avec un cœur large.
Il y a aussi Teech Lab, qui est l'occasion d'étudier le plaisir en programmation, donc si vous êtes intéressé par le développement de logiciels, assurez-vous de jeter un œil!

table des matières