# m0leCon Beginner CTF 2023`` ## 1. Ungessable ![image](https://hackmd.io/_uploads/r15MsWcS6.png) ![image-1](https://hackmd.io/_uploads/HkoGi-cBp.png) Đa số mấy bài guess kiểu này thường không thể guess được 🤣 Vô check source xem thử ```javascript <script> const loader = document.getElementById("loader"); const card = document.getElementById("resultCard"); const text = document.getElementById("resultText"); function advance() { const width = parseInt(loader.style.width); if (width < 100) { loader.style.width = `${width + 1}%`; loader.innerText = `${width + 1}%`; } return width; } const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function load() { loader.parentElement.removeAttribute("hidden"); let width = 0; while ((width = advance()) < 100) { await sleep(width == 98 ? 5000 : Math.random() * 100); } loader.style.width = "0%"; loader.parentElement.setAttribute("hidden", ""); } function update(res) { if (res === "wrong") { card.style.backgroundColor = "red"; text.innerText = "Wrong, try again"; } else { card.style.backgroundColor = "green"; fetch("/vjfYkHzyZGJ4A7cPNutFeM/flag") .then((response) => response.text()) .then((str) => { text.innerText = str }); } card.removeAttribute("hidden"); } document.getElementById("guessBtn").onclick = function () { card.setAttribute("hidden", ""); load().then(() => fetch("/guess", { body: document.getElementById("guess").value, method: "POST", })) .then((response) => response.json()) .then((json) => update(json["result"])) .then(() => loader.parentElement.setAttribute("hidden", "")); }; </script> ``` - Nôm na là fetch sẽ gửi một yêu cầu POST đến `/guess` kèm theo giá trị mà mình đoán - Kết quả trả về được chuyển thành json và truyền giá trị của key `result` vô hàm **`update`** - Nếu kết quả khác `wrong` thì sẽ thực hiện fetch từ `/vjfYkHzyZGJ4A7cPNutFeM/flag` về và lấy kết quả đó hiện thị ra màn hình </br> Mình sẽ thử fetch `/vjfYkHzyZGJ4A7cPNutFeM/flag` về xem sao ```javascript jurl = 'https://unguessable.challs.m0lecon.it/vjfYkHzyZGJ4A7cPNutFeM/flag' fetch (url) .then(res => { return res.text() }) .then(flag => { console.log(flag) }) ``` ![image-2](https://hackmd.io/_uploads/SJlEsZqr6.png) Ú là la Hoặc có thể truy cập vào endponit `/vjfYkHzyZGJ4A7cPNutFeM/flag` để lấy flag ![image-3](https://hackmd.io/_uploads/Skt4o-qB6.png) Flag: **~~`ptm{4lw4y5_ch3ck_th3_50urc3_c0d3}`~~** ## 2. SecureAcess ![image](https://hackmd.io/_uploads/rkpdjWqB6.png) Nhìn có vẻ bài này phải kết hợp với `rev` để làm được ![image-1](https://hackmd.io/_uploads/rkzKsWqBa.png) Mình thử login với username là `admin` ![image-3](https://hackmd.io/_uploads/ryYtoZ5BT.png) Có vẻ như mình phải tính toán `2F781F93-C662-4B7C-BE86-983E5A9C29FC` để lấy được `ACCESS TOKEN` Mình có thử với các username khác nhưng vẫn thu về token y hệt Mình có ném file `leaked.pyc` cho thằng bạn rev ```python import hashlib import json import base64 def generate_token(nonce = None): username = 'user001' secret = hashlib.sha256(username.encode() + nonce.encode()).hexdigest() bundle = { 'user': username, 'secret': secret } return base64.b64encode(json.dumps(bundle).encode()) ``` Hiểu nôm na là hàm **`generate_token`** sẽ generate ra một token được `base64_encode` với đối số là `nonce` nếu không truyền thì mặc định là `None` Mình sẽ thử truyền token bên trên vào hàm thử xem nó trả về token gì cho mình ![image-4](https://hackmd.io/_uploads/Hy0Kib5BT.png) **`eyJ1c2VyIjogInVzZXIwMDEiLCAic2VjcmV0IjogImZjZjNjYTNjNTQ4NDBlMzJiN2U5YzUyMDVmODFhNDJlODAwNTU4NjljZWQ4ODM5NmJkNjFhZGQyZWMwOWY4YjMifQ==`** Khả năng cao đây là `ACCESS TOKEN` mà nó bắt mình tính ![image-5](https://hackmd.io/_uploads/BJbqib5rT.png) Ú là la Flag: ~~**`ptm{m4yb3_7he_A1s_4r3_n0t_th4t_5m4r7}`**~~ ## 3. PianoCarriera ![image](https://hackmd.io/_uploads/B1EZnb9H6.png) ![image-1](https://hackmd.io/_uploads/ByL-n-qST.png) Nhìn sơ qua thì có lẽ mình phải tick được `Internship` để đăng ký được môn học <br> ![image-2](https://hackmd.io/_uploads/Sk9b2-cHT.png) Nhưng có vẻ không dễ dàng gì Vô check source xem thử <br> Để ý có đoạn này ![image-3](https://hackmd.io/_uploads/HkpZ2-qSp.png) Nôm na là nó sẽ không cho tick những thẻ nào có class là `noProp` Hướng làm của mình là sẽ tìm những thẻ này và remove class `noProp` đi <br> script ```javascript var elements = document.querySelectorAll('.noProp') elements.forEach(element => { element.classList.remove('noProp') }) ``` ![image-4](https://hackmd.io/_uploads/BJzGhbqBT.png) Có vẻ như mình đã tick được khóa `Internship` rồi ![image-5](https://hackmd.io/_uploads/ByLf2b5Sp.png) Nhưng đời không như là mơ Có vẻ như nó yêu cầu mình phải chọn đủ 30 tín chỉ, nhưng học phần `Internship` chỉ mới có 12 <br> Lúc đầu mình có tìm cách để chuyển số tín chỉ của `Internship` lên thành 30 nhưng có vẻ không được Sau một hồi suy nghĩ thì sao mình không chọn thêm học phần để nó đủ 30 tín chỉ?? ![image-6](https://hackmd.io/_uploads/Hyozhb9BT.png) Mình sẽ chọn thêm thằng `Thesis` bên dưới có tín chỉ là 18 để đủ 30 tín, trùng hợp là nó có class `noProp` và mình đã tiện thể remove trước đó <br> ![image-7](https://hackmd.io/_uploads/S1O7nWqSp.png) Giờ đi confirm thôi ![image-8](https://hackmd.io/_uploads/SyjQ3-5r6.png) Ú là la Hoặc có thể làm theo cách này ![image-9](https://hackmd.io/_uploads/rkg42W5B6.png) Mình sẽ intercept của thằng `Tesi` ![image-10](https://hackmd.io/_uploads/SyVNnW9rp.png) Sau đó mình thay đổi `cod_ins` từ thằng `Tesi` thành `Internship` ![image-11](https://hackmd.io/_uploads/HkwN3W9rp.png) Và sau đó đi confirm và lấy flag ![image-12](https://hackmd.io/_uploads/BJpE3Z9rT.png) Flag: ~~**`ptm{p0p1P0P1_d1_70r1n0}`**~~