# TJCTF-2023 ## WEB ### hi Ở bài này khi bắt đầu thì chall thì chúng ta sẽ không nhận ra gì cả ![Imgur](https://i.imgur.com/xgAY3Ac.png) Checksource để biết thêm thông tin ![Imgur](https://i.imgur.com/SqavfZ0.png) Flag: `tjctf{pretty_canvas_577f7045}` ### swill-squill Bài cho chúng ta nhập đầu vào với `name` và `grade` ![Imgur](https://i.imgur.com/pb6MyBS.png) Khi register xong thì trang sẽ redirect đến endpoint `/api` và hiện thông tin người dùng ![Imgur](https://i.imgur.com/GRb0QZj.png) Check source: ![Imgur](https://i.imgur.com/I3Omvn0.png) ![Imgur](https://i.imgur.com/hBomeGx.png) Nội dung của `admin` sẽ có chứa flag vì vậy chúng ta cần phải đăng nhập dưới tên `admin`, redirect đến `api` và lấy flag Tuy nhiên, chúng ta sẽ không thể register dưới tên admin và ở bài này chúng ta sẽ dựa vào lỗ hổng SQLi ![Imgur](https://i.imgur.com/JoHTb2n.png) Payload: name = `' OR 1=1 --` ![Imgur](https://i.imgur.com/JAOgVqd.png) Flag: `tjctf{swill_sql_1y1029345029374}` ### outdated ![Imgur](https://i.imgur.com/t4aienl.png) Chall này sẽ cho chúng ta upload một file python và sau đó sẽ hiện ra output ![Imgur](https://i.imgur.com/va5tLlu.png) OK. Vậy ý tưởng là ở đây chúng ta sẽ chạy OS command, tuy nhiên khi check source code chúng ta sẽ thấy có một blacklist: ![Imgur](https://i.imgur.com/ooDgsB9.png) Chặn `import`, vậy là cách làm ở đây cũng sẽ gần giống các payload khi chúng ta làm SSTI. Tuy nhiên kể cả `globals`,`sys`,`open` cũng bị chặn và từ đó những payload thông thường cũng không thể dùng được. Sau khi đi dò từng chút một thì ta có payload: Payload 1:`print(().__class__.__mro__[1].__subclasses__()[84]().load_module('os').__dict__['sy'+'stem']('cat f*'))` Payload 2:`print([x for x in ()._class__.__base__.__subclasses__() if x.__name_ == "_wrap_close"][0].__init__.__globals__['system']('ls'))` ![Imgur](https://i.imgur.com/XJlLZOB.png) Flag: `tjctf{oops_bad_filter_3b582f74}` ### pay-to-win Một bài liên quan đến brute-force để crack. Vào bài sẽ cho chúng ta nhập username và redirect đến trang chính: ![Imgur](https://i.imgur.com/ovFe5Yz.png) Sẽ có chứa 2 `Cookie` là `data` và `hash`. Check source: ![Imgur](https://i.imgur.com/4ruOZvQ.png) Ở dòng 55,56 ta có thể coi như nó đang tạo ra 1 `key` với độ dài 24 bit: ```python if username not in users: users[username] = hex(random.getrandbits(24))[2:] ``` Sau đó từ dòng 65 đến 72 thì tạo ra 2 dữ liệu với rồi setup cookie: + `b64data` chứa dữ liệu người dùng bao gồm `username` và `user_type` đã được encode base64 + `data_hash` là dữ liệu của `b64data` và `key` Khi vào trang chính, trang sẽ check các giá trị và so khớp với nhau để bảo đảm tính toàn vẹn: ![Imgur](https://i.imgur.com/Nh7TgHh.png) Nếu `user_type` phù hợp thì sẽ để cho chúng ta set theme. Để lấy flag bài này chúng ta sẽ có đường đi như sau: + Xác định nơi có flag ![Imgur](https://i.imgur.com/j1Jkgoz.png) + Truy cập dưới `user_type` là **prenium** để set theme dẫn tới đọc file có flag + Tìm ra key để có thể thay đổi `b64data` và `data_hash` Solve code: https://github.com/NamMTA892/TJCTF_2023/blob/main/pay-to-win-solve.py Flag: `tjctf{not_random_enough_64831eff}` ### ez-sql Lại một bài SQLi nữa nhưng ở đây chúng ta sẽ có chút lưu ý: ![Imgur](https://i.imgur.com/xbKDFUE.png) Tên `flag table` sẽ chứa uuid có độ dài 128bit nhưng ở phần truy vấn: ![Imgur](https://i.imgur.com/xmJQpIm.png) Độ dài `name` không quá 6 ký tự. Vậy làm sao để giải quyết được bài này ??? Ở đy chúng ta sẽ có 1 trick: ![Imgur](https://i.imgur.com/AyfXH7w.png) ![Imgur](https://i.imgur.com/NflP8yk.png) Sử dụng SQLmap: Flag: `tjctf{ezpz_l3mon_squ33zy_603f8308}` ### back-to-the-past Bài này là một dạng bypass qua JWT để có thể lấy được flag. Cùng check source nào: ![Imgur](https://i.imgur.com/zPdVnu9.png) ![Imgur](https://i.imgur.com/eXUCqGJ.png) OK, vậy là chúng ta không thể tạo năm nhỏ hơn 1970 rồi. Cùng xem qua cách tạo token nào: ![Imgur](https://i.imgur.com/AKc8g36.png) Và phương pháp decode để lấy dữ liệu: ![Imgur](https://i.imgur.com/EsxN1tV.png) ![Imgur](https://i.imgur.com/bCF4832.png) Vậy theo flow của bài này thì đầu tiên sẽ tạo ra Token với `algorithm` mặc định là RS256. Sau đó được nhận `alg` từ `json_header` và decode theo phương pháp đó. Từ đây chúng ta có thể làm mất đi phần xác thực `Signature` bằng cách để `alg` là **NONE** Solve code: https://github.com/NamMTA892/TJCTF_2023/blob/main/back-to-the-past-solve.py Setup cookie và vào endpoint `retro` để lấy flag. Flag: `tjctf{very_very_retro_3bbff613}` ###