YesWeHack Dojo #35 : Chatroom

Dojo #35 - Chatroom Introduction The 35th Dojo Challenge, Chatroom, invited participants to exploit a CWE-73: External Control of File Name or Path vulnerability and read a file containing the challenge flag. YesWeHack asked to produce a qualified report explaining the logic allowing exploitation, as set out by the challenge. Here’s my write-up for this challenge, which unfortunately didn’t make the top 3 :(. Setup Code const child_process = require('child_process') const process = require('process') const path = require('path') const ejs = require('ejs') const fs = require('fs') process.chdir("/tmp") // Flag fs.writeFileSync('flag.txt', flag) // Design fs.writeFileSync('index.ejs', ` <html> <body> <div class="wrapper"> <div class="base contacts"> <div class="header"> <input type="text" placeholder="Search..."> <img class="icon" src="https://api.iconify.design/ic:baseline-search.svg?color=%23fff"> </div> <ul> <li> <img class="profile" src="https://static.vecteezy.com/ti/gratis-foton/p1/22717360-sot-kanin-med-morot-vaska-tecknad-serie-ikon-illustration-djur-utbildning-ikon-begrepp-isolerat-generat-ai-gratis-fotona.jpg"> <div class="user"> <p>Root</p> <div class="status"> <div class="dot-active"></div> <p style="font-size: 14px;"> Online</p> </div> </div> </li> <li> <img class="profile" src="https://static.vecteezy.com/ti/gratis-foton/p1/22716493-sot-bi-flygande-tecknad-serie-ikon-illustration-djur-natur-ikon-begrepp-isolerat-generat-ai-gratis-fotona.jpg"> <div class="user"> <p>Hackerman</p> <div class="status"> <div class="dot"></div> <p style="font-size: 14px;"> Offline</p> </div> </div> </li> <li> <img class="profile" src="https://static.vecteezy.com/ti/gratis-foton/p1/22711661-hacker-rorelse-en-barbar-dator-tecknad-serie-ikon-illustration-teknologi-ikon-begrepp-isolerat-platt-tecknad-serie-stil-generat-ai-gratis-fotona.jpg"> <div class="user"> <p>Pwner</p> <div class="status"> <div class="dot"></div> <p style="font-size: 14px;"> Offline</p> </div> </div> </li> <li> <img class="profile" src="https://static.vecteezy.com/ti/gratis-foton/p1/30493982-sot-tecknad-serie-robot-med-horlurar-och-gul-blommor-vektor-illustration-ai-genererad-gratis-fotona.jpg"> <div class="user"> <p>Robo7</p> <div class="status"> <div class="dot"></div> <p style="font-size: 14px;"> Offline</p> </div> </div> </li> </ul> <img class="settings" src="https://api.iconify.design/solar:settings-bold.svg?color=%23999da5"> </div> <div class="base chat"> <div class="header"> <img class="profile" src="https://pbs.twimg.com/profile_images/1576633593203392513/7lbM_Fd0_400x400.jpg"> <p class="user" style="font-size: 22px;">Brumens</p> <div class="dot-active"></div> <img class="icon" src="https://api.iconify.design/majesticons:microphone.svg?color=%23fff"> <img class="icon" src="https://api.iconify.design/majesticons:video-camera.svg?color=%23fff"> <img class="props" src="https://api.iconify.design/mdi:dots-vertical.svg?color=%23999da5"> </div> <div class="msg"> <div class="dm1"> Hello there, so you trying to exploit this code injection? &#128526; </div> <div class="dm2"> Yes, leave me alone... &#129402; </div> </div> <div class="footer"> <img src="https://api.iconify.design/material-symbols:add-circle.svg?color=%23999da5"> <% if ( message != null ) { %> <input type="text" placeholder="<%= message %>"> <% } else { %> <input type="text" placeholder="Message..."> <% } %> <button>Send</button> </div> </div> </div> <a class="ref" href="https://www.vecteezy.com/free-vector">Images by Vecteezy</a> <!-- Only design below (ignore) --> <style> @import url('https://fonts.googleapis.com/css2?family=Anta&family=Bungee+Shade&family=Clicker+Script&family=Indie+Flower&family=Inter+Tight:ital,wght@0,100..900;1,100..900&family=League+Spartan:wght@100..900&family=Madimi+One&family=Nabla&family=Sunflower:wght@300&display=swap'); :root { --color-shadow: rgb(0,0,0,0.33); --color-btn: #7d8fc5; --color-bg: #36393e; --color-primary: #424549; --color-border: #707377; --color-transparent: rgba(255, 255, 255, 0.2); --color-txt: #999da5; --color-offline: rgb(217, 42, 42); --color-online: #5de423; } body { margin: 0px; padding: 0px; background-color: var(--color-bg); color: var(--color-txt); font-family: "Madimi One", sans-serif; font-weight: 600; font-style: normal; object-fit: cover; width: 100%; height: 100%; } input { background-color: var(--color-primary); color: var(--color-txt); border: 1px solid var(--color-border); margin: 4px; border-radius: 13px; padding-left: 10px; font-size: 16px; } button { cursor: pointer; text-decoration: none; background-color: var(--color-btn); color: #fff; border: 0; border-radius: 13px; width: 100px; height: 50px; font-size: 16px; font-weight: 900; margin: 4px; transition: 0.3s; } .icon { cursor: pointer; transition: 0.3s; width: 24px; height: 24px; } .icon:hover { transform: translate(0, 3px); } button:hover { transform: translate(0, 3px); } li { margin-top: 10px; display: flex; list-style: none; } .wrapper { position: absolute; width: 100%; height: 100%; display: flex; } .profile { margin: 8px; width: 50px; height: 50px; border-radius: 50%; border: 2px solid var(--color-border); } .contacts { border: 2px solid var(--color-border); box-shadow: 0 5px 20px var(--color-shadow); padding: 10px; flex: 30%; margin: 20px; border-radius: 22px; background-color: var(--color-primary); backdrop-filter: blur(3px); height: 100%; } .contacts input { width: 100%; height: 32px; } .contacts .header { display: flex; align-items: center; } .contacts .header .icon { background-color: var(--color-btn); border-radius: 50%; padding: 8px; } .contacts ul { margin: 0; padding: 0px; } .contacts ul li { border: 2px solid var(--color-border); border-radius: 13px; background-color: var(--color-primary); } .user .status { display: flex; align-items: center; } .dot { margin-right: 4px; width: 12px; height: 12px; background-color: var(--color-offline); border-radius: 50%; } .dot-active { margin-right: 4px; width: 12px; height: 12px; background-color: var(--color-online); border-radius: 50%; } .contacts .settings { border-radius: 50%; position: absolute; padding: 8px; width: 32px; height: 32px; bottom: 10; left: 10; } .chat { border: 2px solid var(--color-border); box-shadow: 0 5px 20px var(--color-shadow); padding: 10px; flex: 70%; margin: 20px; margin-left: 0px; border-radius: 22px; background-color: var(--color-primary); backdrop-filter: blur(3px); height: 100%; } .chat .header { border-radius: 19px 19px 0 0; padding-bottom: 10px; display: flex; align-items: center; gap: 20px; width: 100%; } .user { padding: 6px; } .user p { font-weight: 900; font-size: 16px; margin: 0; } .user .status { text-align: center; border-radius: 12px; height: 20px; width: 60px; padding: 4px; padding-left: 8px; padding-right: 8px; background-color: var(--color-bg); margin: 0; } .chat .profile { width: 80px; height: 80px; } .chat .icon { background-color: var(--color-btn); padding: 8px; border-radius: 50%; } .chat .props { padding: 6px; position: absolute; width: 32px; height: 32px; right: 50px; } .chat .msg { border-radius: 22px; padding-bottom: 10px; border: 2px solid var(--color-border); background-color: var(--color-bg); height: 50%; } /*I'm lazy*/ .chat .dm1 { border-radius: 22px 22px 22px 0; background-color: var(--color-btn); margin-left: 8px; margin-top: 20px; color: #fff; font-size: 20px; text-align: left; padding: 20px; width: 220px; height: 80px; } .chat .dm2 { position: absolute; border-radius: 22px 22px 0 22px; background-color: var(--color-btn); margin-right: 20px; margin-top: 3%; color: #fff; font-size: 20px; text-align: left; right: 0; padding: 20px; width: 220px; height: 30px; } .chat .footer { display: flex; justify-content: center; align-items: center; border-radius: 0 0 19px 19px; height: 100px; } .chat .footer { height: 70px; } .chat .footer img { border-radius: 50%; padding: 8px; width: 38px; height: 38px; } .chat .footer input{ width: 320px; height: 50px; } .ref { position: absolute; margin: 12px; color: #fff; bottom: 0; right: 0; font-weight: 100; font-size: 12px; } </style> </body> </html> `) return {fs, ejs, path, process, child_process} class Message { constructor(to, msg) { this.to = to; this.msg = msg; this.file = null } send() { console.log(`Message sent to: ${this.to}`) } makeDraft() { this.file = path.basename(`${Date.now()}_${this.to}`) fs.writeFileSync(this.file, this.msg) } getDraft() { return fs.readFileSync(this.file) } } const userData = decodeURIComponent("") var data = {"to":"", "msg":""} if ( userData != "" ) { try { data = JSON.parse(userData) } catch(err) { console.error("Error : Message could not be sent!") } } var message = new Message(data["to"], data["msg"]) message.makeDraft() console.log( ejs.render(fs.readFileSync('index.ejs', 'utf8'), {message: message.msg}) ) Description When a message is sent, it is saved in the same folder as the index.ejs file. The path.basename function is used to attempt to secure the retrieval of the username in the to POST parameter. ...

September 25, 2024 Â· 8 min Â· Aether

PwnMe CTF 2023 : Pwn Unintended Write-Up - CPython101

Unintended CPython101 From May 5th to 7th the second edition of the PWNME CTF was held**. Our team participated in the student category. For this write-up, I will explain how I was able to bypass the intended way to flag the Pwn CPython101 challenge. CPython101 What if you could do memory corruption in Python ? Well this is an opportunity for you to discover that ! Find a way to read the flag on the remote service. **Note**: - *This challenge is not a pyjail, mesures have been taken to block unintented way. If you find a bypass to the challenge please report to the challenge maker :)* - *You must spawn an instance for this challenge. You can connect to it with netcat: nc 51.254.39.184 1338* Author: Express#8049 Analysis The challenge gave us an archive that contains a Dockerfile and the vulnerable pwnme.so library, which is a Python module written in C. There is also a wrapper that takes our Python code and places it into a file that will be executed later. ...

May 10, 2023 Â· 4 min Â· Aether

FCSC 2023 : Follow the Rabbit

Follow the Rabbit Tandis qu'Alice s'occupait de son jardin, elle est tombée sur un lapin blanc affolé. Celui-ci, pressé, lui a demandé de le suivre. Sans hésiter, Alice a décidé de le poursuivre dans son mystérieux terrier. https://follow-the-rabbit.france-cybersecurity-challenge.fr SHA256(follow-the-rabbit-public.tar.gz) = 6d5af5b83e3c9d3d5bb556965440df80507406239e68ef94c03ba1482d99f411. Analyse Le challenge nous offre une archive contenant des fichiers docker ainsi que le code source de la configuration nginx. docker-compose.yml: version: '3' services: follow-the-rabbit: build: context: . args: FLAG: FCSC{flag_placeholder} ports: - 8000:80 Dockerfile: ...

April 30, 2023 Â· 5 min Â· Aether

FCSC 2023 : Hello from the inside

Hello from the inside Votre nouveau stagiaire aimerait bien vous persuader que les architectures orientées micro-service améliorent nettement la sécurité de vos systèmes d'information. Il a décidé de vous le démontrer en réalisant une preuve de concept du type "Hello world", déployé à la hâte sur un serveur HTTP Apache. Allez-vous lui proposer un contrat à la fin de son stage ? https://hello-from-the-inside.france-cybersecurity-challenge.fr/ Note : Aucun bruteforce n'est nécessaire à la résolution du challenge. Analyse Le code source n’est pas donné pour ce challenge, visitons dans un premier temps le site. ...

April 30, 2023 Â· 2 min Â· Aether

FCSC 2023 : Peculiar Caterpillar

Peculiar Caterpillar Alors qu'elle se promenait au Pays des merveilles, Alice tomba sur une chenille étrange. À sa grande surprise, cette dernière se vantait d'avoir construit son propre site web en utilisant Javascript. Bien que le site semblait simple, Alice ne pouvait s'empêcher de se demander s'il était vraiment sécurisé. https://peculiar-caterpillar.france-cybersecurity-challenge.fr/ SHA256(peculiar-caterpillar-public.tar.gz) = 0aad816ba8eeff048785257f1bc157e83e59ec3246af0f9556ef7b6e39b56b6f. Analyse Le challenge nous offre une archive, contenant plusieurs fichiers intéressants. On apprend notamment que l’application est codée en Node.js et qu’elle utilise deux dépendances. ...

April 30, 2023 Â· 4 min Â· Aether

FCSC 2023 : Tweedle Dum

Tweedle Dum Au cours de ses aventures au Pays des merveilles, Alice a rencontré une curieuse paire de jumeaux : Tweedledee et Tweedledum. Les deux avaient créé un site web simpliste en utilisant Flask, une réalisation qui a suscité l'intérêt d'Alice. Avec son esprit curieux et son penchant pour la technologie, Alice ne pouvait s'empêcher de se demander si elle pouvait pirater leur création et en découvrir les secrets. Note : Tweedle Dum est la version "facile" du challenge, regardez Tweedle Dee pour la version "difficile". https://tweedle-dum.france-cybersecurity-challenge.fr/ SHA256(tweedle-dum-public.tar.gz) = fc9c858fa98401db631b27876e17acf2a9cb25627887cd5d849af6a746a4c646. Analyse Le challenge nous offre une archive dans laquelle on connait les versions de Flask ainsi que le code source de l’application. ...

April 30, 2023 Â· 5 min Â· Aether

Sthack 2022 : Pwn, Reverse

Reverse - JeanLouis Analyse En ouvrant le binaire dans Ghidra et après avoir renommé les variables, on tombe sur une sorte de memcpy d’un shellcode qui sera xoré avec une clé statique ensuite par le programme. Figure 1: Copie du shellcode et XOR de celui-ci. SHELLCODE = "4F274DEB5442071D4F075746544F530743424F42074A484F425D074B4F624953559F232727279C26272727AEC69D3F272727EAA79F242727279C27272727AA6B03C79D37272727EAA7AEE8AD30A7D56AA7DD3928A2CC27272760AD30A7D548A7DD1C28A2FB27272760AD30A7D553A7DD1B28A2EA27272760AD30A7D543A7DD0228A29927272760AD30A7D542A7DD0128A28827272760AD30A7D557A7DD1C28A28727272760AD30A7D546A7DD3D28A2B627272760AD30A7D554A7DD0D28A2A527272760AD30A7D554A7DD31525060AD30A7D542A7DD3B524B60AD30A7D514A7DD71524660AD30A7D514A7DD6D527160AD30A7D545A7DD20526C60AD30A7D546A7DD75526760AD30A7D543A7DD70521260AD30A7D543A7DD3E520D604F0E0E2D274F0042071D4F074D48524F654E42499F232727279C26272727AEC69D28272727EAA7CC1D4D2D4F090909094F544209094F075746544F530743424F54074A484F5251464E4F6A4627279F232727279C26272727AEC69D07272727EAA7CC279F262727279C27272727EAA700" SHELLCODE = bytes.fromhex(SHELLCODE) final_shellcode = bytearray(len(SHELLCODE)) for k in range(0, 0x18b): final_shellcode[k] = SHELLCODE[k] ^ 0x27 print(bytes(final_shellcode)) Il suffit de prendre le shellcode en mémoire de le copier et de placer la valeur hexa dans un site comme defuse.ca pour retrouver les instructions. ...

May 27, 2022 Â· 6 min Â· Aether

Mars@Hack 2022 : Break safe code - 2 Easy

Break safe code - 2 Easy Write-up TL;DR En m’aidant du fichier flowchart.png, je pouvais déduire les fonctions dans le programme. La fonction permettant d’initialiser un code révèle un XOR dynamique en commençant avec la clé 0xc6. Il m’a ensuite suffi de décoder la mémoire EEPROM via le XOR dynamique pour récupérer le code de la boîte. Introduction Le challenge fournit : - un schéma électronique - un schéma du flow d’exécution du programme ...

May 8, 2022 Â· 4 min Â· Aether

Capture The Talent 2022 : Pwn - Global Pandemic (Write-Up)

Global Pandemic This challenge give us the c code and the compiled binary. Figure 1: Global_Pandemic.c The Vulnerability First, at looking at the c code we can see the printf(pass); line. That is a Format Bug String. We can check that if we try to compile with clang. Figure 2: Compilation of the c code with clang. Pre-requirements To obtain the flag, we need to change the admin variable value. To do that, we need to write 0xb4dbabe3 were the address of admin is. ...

February 22, 2022 Â· 2 min Â· Aether

FCSC 2021 : Malware 3-3

Malware 3-3 Ce challenge est un challenge en 3 parties indépendantes, mais dont l'ordre logique est indiqué par les numéros : forensics (1) -> pwn (2) -> reverse (3). /!\ Le programme a de réelles capacités malveillantes /!\ Ouf ! Vous avez réussi à récupérer le malware, à vous connecter sur le serveur de l'attaquant et à récupérer la clé privée (fichier key.priv ci-joint) ayant servi à chiffrer votre précieux flag. Le fichier key.priv portait initialement le nom : 0fdb0eea57198b3bb69e8267690ede5d5ba95ab791638a610372120b773d4acc_2021-03-15|21:34:41.priv. Dechiffrez le fichier flag.txt pour valider cette épreuve. SHA256(malware) = d63087cb4ad44b1bf07646e195e8bc2997ab0dea6119f0ef6c70ddcc51dc7f11. SHA256(flag.txt) = 14474b163650c1e940ae9612e29c4a8a5012f1ee1d31c6262f84e657680568b8. SHA256(key.priv) = 55a4f14531fbc38349687d1a8fb13faa55a52bb8cff5bb23576ca72c595af37f. Tag: reverse ...

May 3, 2021 Â· 10 min Â· Aether