How to Prevent Flag Sharing in CTF Competitions
Flag sharing is the most common form of cheating in CTFs. Per-team flags and real-time detection are the only reliable solutions. Here's how they work.
· 4 min read · Zero Day Arena team
Every CTF with a prize, a ranking or a hiring decision attached has the same problem: one team solves a challenge, and the flag ends up with another team. Sometimes it's a friend in another team. Sometimes it's a Discord channel. Sometimes it's one person playing for two teams.
At GPN CTF 2025, the organizers used team-specific flags and, after the event, queried their submission database: it turned up 53 incidents where a team had submitted another team's valid flag. Per-team flags made every one of those provable. But the search still ran after the scoreboard was final. That's how flag sharing usually gets caught: late, and only because someone made the effort.
Why it happens
Flag sharing is low-effort and low-risk. Copying a string takes two seconds. With static flags, the copy is indistinguishable from a genuine solve, so the only signal is circumstantial: two teams solving the same hard challenge within a minute of each other, or a team with no solves in a category suddenly solving its hardest challenge.
Circumstantial signals generate arguments, not penalties. Fast teams solve things quickly. Teams from the same university think alike. Without proof, most organizers let it go, and the people who notice that are your strongest players.
Why static flags can't be fixed
With a static flag, every team submits FLAG{same_string_for_everyone}. The platform can tell you that a team submitted a correct flag. It cannot tell you where the flag came from.
The common workarounds don't solve that:
- Timing analysis catches only the careless, and produces false positives for teams who are simply fast.
- IP correlation fails with VPNs, shared university networks and conference Wi-Fi.
- Post-event CSV comparison works only if flags differ per team. With static flags, every submission is identical.
- Honor codes set expectations. They don't detect anything.
Per-team flags
The fix is to make every team's flag different, so the flag itself identifies its source.
For each challenge and team, the platform derives a flag from a secret key:
flag = "FLAG{" + HMAC-SHA256(server_key, challenge_id + ":" + team_id)[:24] + "}"
Team A's flag for a challenge is useless to team B. If team B submits it, the platform knows three things immediately: the submission is wrong for team B, the flag is right for team A, and the two teams are connected. That's not a suspicion. It's evidence.
Because the flags are derived with HMAC rather than stored, they can't be predicted without the server key, and there's no list of flags for anyone to leak.
Delivering the flag to the right team
Per-team flags only work if each team sees its own flag. How depends on the challenge type:
- Container challenges: the flag is injected into the team's instance as an environment variable or file at start.
- File-based challenges (forensics, reverse engineering): the platform generates a per-team build of the artifact, or embeds the flag in a per-team download.
- Service challenges: the challenge's backend asks the platform for the requesting team's flag.
Some challenges genuinely can't be personalized, for example OSINT challenges where the answer is a fact. Those stay static, and the platform should tell organizers which challenges they are.
Detect in real time, not after the event
Per-team flags turn detection into a lookup: every incorrect submission is checked against the other teams' valid flags. A match should trigger three things, immediately:
- An evidence bundle: both teams, the challenge, the timestamps, the original solve time, and the submission source.
- A review case: not an automatic ban. Automated systems can be gamed: a team could deliberately submit a rival's flag to frame them. A person should look at it.
- Two-organizer confirmation: penalties require two organizers to agree. It protects against mistakes and against accusations of bias.
Real-time detection also changes behavior. When teams know a shared flag is caught the moment it's submitted, most of them stop trying.
What to put in your rules
Write the anti-cheat policy into your rules before the event:
- Flags are unique per team, and submitting another team's flag is detected automatically.
- Both teams involved, the giver and the receiver, are subject to penalties.
- Penalties range from point removal to disqualification, and require two organizers to confirm.
- Teams can appeal within a stated window.
Publishing it is part of the deterrent.
Zero Day Arena issues per-team HMAC flags for every challenge by default, detects cross-team submissions in real time, and routes them to a two-organizer review queue with the evidence attached. See how it works on a demo.