ECSC 2025 A/D
The European Cybersecurity Challenge 2025 will take place from the 6th to 10th of October 2025 at the COS Torwar Arena in Warsaw. The Attack-Defense CTF will take place on 8th of October, starting at 10:00 CEST and lasting 8 hours until 18:00 CEST.
Attack-Defense
Attack-Defense CTFs are a type of cybersecurity competition in which participating teams host services and attempt to exploit each other over a shared, private network. The goal of the game is to earn points by stealing secrets stored in your opponents' service instances, and to avoid losing points, by preventing your own secrets from being stolen and submitted, all the while keeping the services available and functioning. The team with the most points by the end wins.
CTF Schedule
The schedule for the day of the Attack-Defense CTF:
| Time1 | Event / State change |
|---|---|
| earlier | Players receive credentials to the platform via the ECSC 2025 Discord |
| 09:00 | Players can download wireguard configuration to access the game network |
| 09:30 | Players can start their vulnbox and exploiter using the platform |
| 10:00 | The Attack-Defense CTF officially begins |
| - | SSH access to vulnboxes and exploiters is unblocked |
| - | API endpoints are available to test connectivity |
| - | Flag submission at 10.42.251.2:1337 accepts connections |
| - | Scoreboard at 10.42.251.2 is available (empty) |
| - | Team router and scoreboard respond to pings |
| - | VPN Connection works within but not between teams |
| 11:00 | Network opens and teams can communicate with other vulnboxes |
| 17:00 | The scoreboard scores are frozen |
| 18:00 | The Attack-Defense CTF officially ends |
1 all times CEST
Game Overview
Each team is given root access to a cloud-hosted Linux-based virtual machine that exposes vulnerable services to other teams over a private virtual network.
Over the course of every round, lasting 60 seconds, so-called checkers store text snippets called flags in the services on each team's vulnbox and test their functionality to make sure they are working as intended. Extracting these flags from other teams' services and submitting them to a central flag submission each round to earn ATK-points is the primary goal of the game.
flag stores
A checker may store multiple unique flags each round in distinct areas of a service, and there may be more than one intended vulnerability to reach each one.
To incentivize teams to keep their services available to other teams to exploit, a series of checks is performed each round against every service of every team by the organizers' checkers. These tests define the so-called Service-Level Agreement (SLA); the functionality required for a team to earn SLA-points each round.
attack info
Checkers may provide hints for successfully stored flags to help guide exploits. In some cases, this info is crucial to exploiting the vulnerability at all. It can be retrieved via the attack api.
Each round a team receives DEF-points for every service. The amount of points earned is highest when the service is unexploited and decreases with the amount of other teams exploiting it.
These points combine to calculate the team score using the scoring formula.
Flags
Each flag is matched by the regular expression /^ECSC\{[A-Za-z0-9-_]{32}\}$/
Checkers retrieve flags from the previous 5 rounds in addition to the current round to enable exploits which take longer than a single round to complete. The SLA penalty for missing any of the flags in this retention period incentivizes teams to keep them available for capture.
Flags will award points upon submission for 5 rounds including the round they were deployed in.
Each flag consists of a prefix and suffix, that wrap a base64-encoded1 payload with the following format:
2 bytes: round id2 bytes: team id2 bytes: service id2 bytes: flagstore id16 bytes: SHA256-HMAC (of first 8 bytes)
Flag Submission
Players can submit stolen flags by sending them line-delimited in a plain TCP
connection to 10.42.251.2 on port 1337. This must be done via the game
network, since the source ip is used to determine the submitting team.
For each line, in the order that they are received, the flag submission will return one of the following results on a new line:
[OK]: The flag is valid and was accepted[ERR] Invalid format: The flag is malformed[ERR] Invalid flag: The signature of the flag is incorrect[ERR] Expired: The flag was submitted after the retention period[ERR] Already submitted: The flag has already been submitted by this team[ERR] Can't submit flag from NOP team: The flag submitted is from NOP[ERR] This is your own flag: The flag is from the submitting team
-
This payload is encoded using the base64url charset ↩
Team VMs
Cloud-hosted vulnboxes and exploiter VMs are provided by the
organizers to all teams.
The team router provides access to the
internet via a public IPV4 and IPv6 address, as well as to the game
network through WireGuard. The vulnbox and exploiter are not
reachable from the internet via their public IPv4 or IPv6 address.
Setup
Vulnboxes and exploiters run on OVHCloud infrastructure as C3-32 instances in Warsaw's WAW1 data center. With 16 cores, 32 GB of ram and 400 GB of storage each, the vulnbox and exploiter should have enough resources to run the services, exploit their vulnerabilities, and handle exploit as well as checker traffic.
Self-hosting services is not officially supported, and carries a latency and bandwidth penalty. The Wireguard connection from the vulnbox to the router is established inside a cloud-provider network, which allows for a faster connection than the public interface a self-hosted vulnbox would have to proxy traffic over.
Each vulnbox is configured to accept SSH keys by the organizers in addition to those configured by the teams via the platform. Teams are free to remove these SSH keys, however doing so limits the amount of support and automated fixes the organizers can provide.
Vulnboxes and exploiters are assigned an IPv4 address in the Game Network and the Team Cloud Network.
Firewall
Vulnboxes are provisioned with an iptables firewall that drops all traffic except:
- Ingress connections from the game network to ports exposed by docker
- Ingress connections to SSH (port 22)
- Established connections
- Egress connections
Additionally, the vulnbox is firewall'd at the cloud-provider level from external access to ensure all game-related traffic runs through the router and misconduct can be accounted for.
Players may start their vulnbox 30 minutes before the CTF begins through the platform, but SSH access will be prevented through the team router until the CTF has officially started.
Game Network
The A/D CTF takes place in the game network. Players connect to this network through a WireGuard tunnel. WireGuard configuartion files will be made available one hour before the game starts via the platform. They can be used with standard WireGuard tooling such as wg-quick.
VPN Access
Every WireGuard configuration file allows exactly one host to connect to the game network. Trying to use the same configuration on multiple hosts simultaneously will likely make the connection unstable for all hosts using that configuration. We provide three configuration files to every player, and 10 additional configs per team, which are only accessible to captains and players promoted to Technician on the platform.
The VPN endpoint will be accessible via IPv4 for the infrastructure demo on 28.09.2025, and most likely only via IPv6 for the final CTF.
The configuration files contain credentials and information about the VPN endpoint. Do not share any of this information with anyone outside your team. This includes the endpoint information - it is different for every team. Modifying the configuration files should not be necessary.
The VPN connection is only used to access the game network. Most importantly, your vulnbox, your team members, other teams' vulnboxes, the flag submission, attack info, and the scoreboard. Your devices can not use the VPN connection to access the internet.
Game Network IPs
The game network uses the address range: 10.42.0.0/16.
Every team has its own subnet, the team network: 10.42.<TEAM>.0/24
Each team's vulnbox gets the ip 10.42.<TEAM>.2.
Every team network has a gateway 10.42.<TEAM>.254, controlled by the infrastructure.
Every host connected to the game network has an ip in its team's subnet and is reachable from other hosts in the team subnet.
The NOP (non-playing) team is assigned the team id 1.
Therefore, the NOP vulnbox is available at the ip 10.42.1.2.
The gameserver has the ip address 10.42.251.2, and hosts the scoreboard (port 80),
the flag submission (port 1337) and the Attack API (port 8080).
Access to the vulnbox
Connecting to vulnboxes is only possible through the VPN, including your own team's vulnbox. Vulnboxes can access the internet, but they do not have a designated public ip. They essentially sit behind a NAT. This is done to ensure all interactions can be properly observed by the organizers and any misconduct can be accounted for. It also minimizes opportunities for "opsec fails" and attacks that are likely against the rules of conduct.
Note that the overall bandwidth for each team's in- and outbound VPN traffic is capped at 1.8gbit/s. Keep this bandwidth budget in mind if you intend to extract pcaps from your vulnbox to another host.
Team Cloud Network
Each team's router, exploiter and vulnbox are also connected to an internal cloud network without WireGuard. Connectivity within this network is mostly unrestricted.
This network has the address range: 10.43.<TEAM>.0/24
The vulnbox gets the ip 10.43.<TEAM>.2
The exploiter gets the ip 10.43.<TEAM>.3
The gateway gets the ip 10.43.<TEAM>.254
These addresses of other teams are not reachable via the game network.
Traffic Anonymization
Connections originating from outside your teams network are anonymized to prevent checker fingerprinting.
All connections from checkers and other teams will appear to originate from
10.42.<TEAM>.254 - your team's gateway.
You should consider the following when encountering network issues:
- Packets with IP header options are rejected since they are likely used
unintentionally and are easily fingerprintable. The game network will reply with ICMP type
Destination unreachable(3) and codeAdministratively Prohibited(13). - TCP headers are normalized to prevent teams from telling apart checkers from exploiters via patterns in TCP options / flags usage.
- TTLs of packets entering team networks are capped at 32 such that traffic to vulnboxes arrives with the same TTL regardless from where it was sent.
- TTLs are not decremented in our router mesh to prevent
traceroute-ing of router topology. - We artificially introduce latency and degrade performance to prevent fingerprinting based on network conditions / response time of external exploiters.
- MTU negotiations are dropped to prevent using cached PMTU values to keep a single host fingerprinted.
- TCP MSS is set to a fixed value (MTU - 40) to prevent fingerprinting and potentially causing high packet rates.1
Despite all of this, it might still be advisable to run exploits from the vulnbox if you suspect your traffic is being fingerprinted.
Game Firewall
While traffic within one team is almost unrestricted, traffic between teams is heavily restricted. The only allowed traffic is:
- TCP connections, but only to vulnboxes
- ICMP traffic of type
Echo Request(8),Echo Reply(0) andDestination unreachable(3) with codes 0, 1, 2, 3, 10, and 13.
Note that attacking other teams hosts other than the vulnbox is generally prohibited.
Additionally, the game firewall blocks connections to other teams' vulnboxes in the port range 8000 to 9000 (exclusive). Using this port range for tooling deployed on the vulnbox ensures that it can not be easily accessed by other teams - even if the host firewall would allow it.
Finally, the network drops malformed packets, packets with invalid checksums, and packets that can't be attributed to connections. These firewall rules are designed to protect teams and infrastructure from malicious traffic that does not target the services. You generally won't receive ICMP messages for prohibited traffic, it will just be discarded.
Bandwidth Limits
We impose a bandwidth limit on the sum of traffic between any two distinct teams.
This limit is at least 20mbit/s.
Note that the bandwidth achievable for a single connection between teams may be significantly less than 20mbit/s due to how our traffic anonymization policies affect TCP throughput.
We also impose a bandwidth limit of at least 20mbit/s on connections to the gameserver per team.
Teams should monitor the traffic generated by their exploits to avoid becoming fingerprintable based on latency introduced by hitting the bandwidth limit.
-
The router MTU and MSS values for the final CTF will be announced at a later date, since the onsite connection needs to be tested for this. The infrastructure demo on 28.09.2025 will use an MTU of 1340 and a MSS of 1300. ↩
Platform
The platform at platform.ad.ecsc2025.pl is used for distributing WireGuard configs, collecting player SSH keys, and giving teams control over their cloud-hosted vulnbox instance.
All players are registered ahead of time on the platform, WireGuard configs may be downloaded 1 hour before the CTF begins.
With their accounts, players may submit SSH keys, which will later be deployed onto the vulnbox, as well as download WireGuard configs for accessing the game network through their team-specific router.
Attack API
We provide a documented API on the gameserver (at 10.42.251.2 on port 8080),
which returns filterable game-related information for use by team infrastructure.
Endpoints
You may try the api live at https://api.demo.ad.ecsc2025.pl.
/api/v1/services : Fine-grained service info
This endpoint returns service information, by default for all services.
Data for a specific service may be queried through the
use of URL parameters./api/v1/teams : Fine-grained team info
This endpoint returns team information, by default for all teams.
Data for a specific team may be queried through the
use of URL parameters./api/v1/score : Fine-grained scoring info
This endpoint returns scoring related information, by default for the
current round. Data for a specific round, team and
service may be queried through
the use of URL parameters.An example of a valid response:
/api/v1/attack_info : Fine-grained attack info
This endpoint returns attack info for services, by default for the
current round. Data for a specific round, team,
service or flagstore may be queried through
the use of URL parameters./api/v1/current_round : current round time and id
This endpoint returns the current round id and start time as an ISO-8601
UTC timestamp with second precision.
If the game has not started, this endpoint will return round 0.
/api/v1/next_round : next round time and id
This endpoint waits for the current round to complete before returning the
new round start time as an ISO-8601 UTC timestamp with second precision.
The connection may timeout if the new round has not started after two rounds worth of time./api/faustctf2024/teams.json : Attack Info (FaustCTF 2024)
This endpoint returns attack info in the FaustCTF 2024 /teams.json format.{
"teams": [
# team ids
123, 456, 789,
..
],
"flag_ids": {
# service name : service info
"service1": {
# team id : attack infos for validity period
"123": ["abc123", "def456"],
"124": ["xxx", "yyy"],
..
},
..
}
}
/api/saarctf2024/attack.json : Attack Info (SaarCTF 2024)
This endpoint returns attack info in the SaarCTF 2024 /attack.json format.
{
"teams": [
# team infos
{
"id": 1,
"name": "NOP",
"ip": "10.42.1.2"
},
..
],
"flag_ids": {
# service name : service info
"fooserv": {
# team vulnbox ip : team info
"10.42.1.2": {
# round id : attack info
"123": ["info_flag1", "info_flag2"]
..
},
..
},
"barserv": {
"10.42.1.2": {
"123": "info_single"
},
..
}
}
}
API Details
The API returns attack info generated at the start of the round specified by the request. Scoring data returned by the api is the state of team scores at the start of the round specified in the request.
Round schedule drift
Even though successful rounds are guaranteed to stay aligned with the
round interval of 60 seconds, single rounds may be cancelled in rare cases,
such as when the gameserver needs to be restarted to address an infrastructure
issue. To keep players in sync with the round schedule despite this albeit
rare possibility, please use the /api/v1/next_round endpoint.
Parameters
The first played round of the CTF has the id 1.
Player team ids start at 2, since id 1 is reserved for the NOP Team.
Service ids are indexed starting at 1.
Flagstore ids are indexed starting at 0.
Scoreboard
Any APIs made available through the scoreboard host at 10.42.251.2 on port
80 exist solely for enabling the client-side functionality of the scoreboard.
No guarantees are made for the availability or contents of these APIs.
Scoring Formula
In Jeopardy CTFs, dynamic scoring is used to infer the difficulty of a challenge based on the number of teams that can solve it. This scoring formula applies the same concept to A/D.
In effect, each round is treated as a Jeopardy CTF with the following challenges:
- For each flag you capture, you receive ATK points based on the number of teams that capture that flag.
- For each service and each flag store, you receive DEF points for each actively exploiting team that did not capture your flag, proportional to the number of teams whose flags that team did capture.
Additionally, you gain a fixed amount of SLA points for each deployed flag
that is still valid (submittable for points) and retrievable from the service,
as long as the checker status is SUCCESS
or RECOVERING.
Checker Status
The checker returns one of the following results for each service:
SUCCESSif all flags could be successfully deployed and retrieved, and functionality checks were successful.RECOVERINGif all checks for the current round succeed, but flags from the past 4 rounds are missing.MUMBLEif any functionality checks for the current round failed.OFFLINEif the checker failed to establish a connection to the service.INTERNAL_ERRORif an internal error occurred. Please notify us with context in a ticket.
Implementation
An approximate implementation may be evaluated against real CTF data using our simulator.
However, the following sections provide the most accurate description of the actual implementation. Please reference it in questions about scoring behavior. We try to include real code snippets from the game engine where possible to help with understanding.
Dynamic Scoring
Dynamic scaling is applied to each challenge by using the ECSC 2025 Jeopardy formula.
We use a lower base value to account for the fact that the A/D CTF will
have more dynamically weighted challenges, as we do not want scores to become too large.
Implementation Details
teams: The number of teams who have solved this challenge.base: The maximum number of points that can be earned through a challenge.
The value of a challenge is close to base when the number of solving teams
is low and close to zero when the number of solving teams is
high. In this case, the value will drop down to 8% of base at 40 teams.
Attack Points
To distribute ATK points, the gameserver increases the number of submissions of all valid flags, based on the number of flags submitted each round, and updates their value accordingly. The value of a flag is calculated dynamically based on the number of teams who were able to capture it.
Implementation Details
Context: This function is called per active attacker and for every victim, for each service and flagstore to calculate the value of the stolen flag.
num_submissions: The number of submissions of flag.
The scores of teams who have captured flags previously are updated to reflect the decreased value of those flags by new submissions.
Since an attacker can exploit at most all active teams, which are neither
themselves nor NOP (max_victims), the maximum gain from an exploit is base * max_victims.
Additional ATK points are awarded to each attacking team based on the DEF points that other teams earn from defending against their attacks (more if the exploit is harder to defend against). This prevents scenarios where defenders gain more DEF points than the attacker can gain ATK points simply because the attacking team started attacking (in other words, failed exploit attempts do not affect the score difference between teams).
def attack_adj(live_round: int, flag_round: int,
max_victims: int, num_victims: int, num_attackers: int):
checker_status = defaultdict(lambda: "SUCCESS")
flag_avail_in = defaultdict(lambda: defaultdict(lambda: True))
pts = defense_scaled(live_round, flag_round, checker_status, flag_avail_in,
max_victims, num_victims, num_attackers, True)
for flag in flags_stolen:
pts += attack(flag.num_submissions)
return pts
Implementation Details
Context: Each round, this function is called per attack, for the service and flagstore bein attacked by an attackers, to calculate the value of the entire attack over all victims.
flag.num_submissions: The number of submissions for the flag of the current victim.flags_stolen: The flags stolen for this service and flagstore by the attacker that were deployed inflag_round.max_victims: The number of teams who are not the attacker or NOP, that have atleast one service not inOFFLINEstate in the current round.num_victims: The number of teams exploited by the attack which points are currently being calculated for.num_attackers: The number of teams attacking this service and flagstore, and obtaining flags stored in flag_round.
Defense Points
To calculate DEF points, the gameserver updates the amount of captures of every flag which is still valid. For each team, the points gained from defending against a specific attacker are calculated dynamically based on the number of teams that were (or were not) exploited by them in that flag store in that round. This is meant to reflect that some exploits may be much more difficult to defend against than others and rewards teams that can construct solid defenses.
This value is scaled by the number of active teams (excluding the attacking team and NOP), and divided by the number of attackers for that flag store. Defense points are only awarded for active attackers, i.e., those teams that submit at least one flag from that flag store and round. If no teams are exploited, no teams receive DEF points.
def defense(max_victims: int, num_victims: int,
num_attackers: int, exploited: bool):
if exploited or num_victims == 0:
return 0
return jeopardy(max_victims - num_victims) * max_victims / num_attackers
Implementation Details
Context: Each round, this function is called per service and flag store, for each active attacker and for every team, to update the value of teams defending / not defending the attack.
max_victims: The number of teams who are not the attacker or NOP, that have atleast one service not inOFFLINEstate in the current round.num_victims: The number of teams exploited by the attack which points are currently being calculated for.num_attackers: The number of teams submitting flags from this service and flag store deployed in a specific round.exploited: Is this team currently being exploited?
The defense points are scaled so that an ideal patch that blocks all
active attackers does not gain more points than the attacker would from the
exploit itself. When a patch blocks all attackers, it gains
defense(..) * num_attackers or jeopardy(max_victims - num_victims) * max_victims / num_attackers * num_attackers points, which is at most base * max_victims (the same as for attack points
but significantly harder to achieve).
To ensure that deleting flags in your own service is not a viable strategy for earning DEF points, we award the defense points for a flag spread across all rounds for which this flag must be retained. If a flag is unavailable in a specific round, no defense points are awarded for that flag in that round. Intuitively, this reflects the idea that defense points should be gained for successful defending; if no flags are at risk, no reward is earned.
def defense_scaled(live_round: int, flag_round: int, checker_status: dict[int, str],
flag_avail_in: dict[int, dict[tuple[int, int, int, int], bool],
max_victims: int, num_victims: int, num_attackers: int, exploited: bool,
flag_rounds_valid: int = 5):
pts = 0
max_round = max(live_round + 1, flag_round + flag_rounds_valid)
for round in range(flag_round, max_round):
if checker_status[round] not in {"SUCCESS", "RECOVERING"}:
continue
if flag_avail_in[round][flag_round, team, service, flagstore]:
pts += defense(max_victims, num_victims, num_attackers, exploited) \
/ flag_rounds_valid
return pts
Implementation Details
Context: Each round, this function is called per service and flag store, for each active attacker and for every team, to update the value of teams defending / not defending the attack.
live_round: The round of the game in which the defense points are being updated.flag_round: The round of the game in which the flag being stolen was deployed.checker_status: The status of the checker for this service for each round of the game.flag_avail_in: A mapping for which flags were retrievable from a specific specific round (first key), depending on the team, service, flagstore and round they were deployed in. Remember: each round the checker checks that valid flags can be retrieved.max_victims: The number of teams who are not the attacker or NOP, that have atleast one service not inOFFLINEstate in the current round.num_victims: The number of teams exploited by the attack which points are currently being calculated for.num_attackers: The number of teams attacking this service and flagstore, and obtaining flags stored in flag_round.exploited: Is this team being exploited by the attack which points are currently being calculated for?flag_rounds_valid: The number of rounds each flag is valid for.
Since defense points are recalculated for rounds in which still-valid flags
were deployed, max_round eventually reaches flag_round + flag_rounds_valid.
At the end of the game, some flags need to be retained for fewer rounds. This means that protecting these flags earns proportionally fewer points over time, as there was also less time for other teams to capture them. However, the total number of flags you need to protect (and thus the defense points that can be earned in each round) does not change at the end of the game.
SLA Points
To determine SLA points, the gameserver calculates the ratio between the number of valid flags retrievable from a service and the number of rounds a flag is valid for.
def sla(checker_status: str, flags_avail: int,
base: int = 10, flag_rounds_valid: int = 5):
if checker_status == "SUCCESS":
return base * flagstores
elif checker_status == "RECOVERING":
return base * flags_avail / flag_rounds_valid
else:
return 0
Implementation Details
Context: Each round, this function is called per team and per service.
checker_status: The status returned by the checker for team and service.flags_avail: The number of flags available in the last 5 rounds from all flagstores of service for team.base: The maximum value of each challenge, seejeopardy(..)definition.flag_rounds_valid: The number of rounds each flag is valid for.
This means that at the start of the CTF, SLA points ramp up from zero to base
over the first five rounds, as the validity period is five rounds long.
Total Points
The total score is the sum of the ATK (attack_adj), DEF (defense_scaled) and SLA (sla) components.
Notes
- Since the capture count of each stored flag determines its worth, attackers are rewarded based on how difficult it is to exploit each specific team.
- The same goes for defense; a patch is rewarded based on the number of other teams that could not defend against the exploiting team. If a vulnerability is harder to patch or a specific exploit is harder to defend against, successfully doing so earns more defense points.
- Not attacking a team effectively gives that team defense points. Thus, there is an additional incentive to attack as many teams as possible beyond attack points. Teams will need to decide if the points gained from not attacking a team offset the expected loss of having the exploit stolen from the attack traffic.
- The maximum points gained from defending a flag store are never more than an exploiting team stands to gain.
- The NOP team does not gain attack or defense points.
Aggregated Scoring
After the Jeopardy and A/D CTF, teams' scores in these two categories are combined to yield a single final scoreboard, which should fairly represent the skill demonstrated in both contests.
Our goal in using the same dynamic scaling as the Jeopardy CTF is that the final team scores of both scoreboards approximate player skill with points in the same way, and thus allow for fairer merging.
The Jeopardy and A/D score are merged using the following formula from the handbook:
ad_normalized_score = ad_score * (jeopardy_winner / ad_winner)
aggregated_score = jeopardy_score + ad_normalized_score
Since defense points are awarded for not being attacked, and NOP team is never awarded defense points, NOP team score represents a team which only managed to keep their services up, without exploiting anyone or defending against any exploits (by not receiving DEF points for any of them).
To avoid SLA points from inflating ad_score before merging and thus
devaluing Jeopardy challenges, we subtract the NOP team score in the
final scoreboard.
FAQ
Why is our team losing defense / attack points?
Teams may appear to lose defense or attack points when the value of the attacks they defended against or the flags they submitted decreases. This calculation is retroactive, as flags may be submitted up to 4 rounds after the round in which they are deployed.
Why are the defense points not zero in a round our service status is neither SUCCESS or RECOVERING?
Most likely, a team was attacking your service before it went down and submitted (at least some of) those flags in the round before it went down. These flags are only considered in the next round, and you are then awarded defense points for defending against this exploit from the previous round retroactively. Crucially, you do not gain defense points for any flag stores not retrievable in the round in which your service was down.
Why are the defense points zero in the first round after our service is available if we didnt get exploited?
The defense points may be zero in this round because no other team is attacking the flag store yet. Attackers typically rely on attack info, which is only released in the subsequent round. If your service was unavailable for multiple rounds before this one, then no team will have attack info to attack the service with in the first round it is available.
Rules of Conduct
Be nice to each other. ECSC is a competitive event, but also an opportunity for teams to learn from each other and have fun. Players should help foster that environment.
The following rules outline behavior prohibited during the competition, beyond those defined by common law (and common sense):
- Sharing flags, challenge details or solutions to anyone outside your own team before the end of the competition is strictly prohibited.
- Giving or accepting assistance from anyone outside the own team and organizers for issues related to the competition is strictly prohibited.
- Gathering and / or taking advantage of insider information relating to the competition is prohibited.
- Attempting to elicit unintended behavior in any devices or services not designated as challenges for the competition running in the game network is strictly forbidden.
- Physically interacting or digitally tampering with the physical infrastructure provided by the organizers without permission is prohibited.
- Any action with the effect of creating excessive load for the contest or team infrastructure is prohibited, even if such actions are in the interest of the competition.
- If you are not sure if something is allowed or not, use the ticketing system to ask before doing it.
- Any unfair behavior with respect to the competition or the other players is forbidden, even if not explicitly described in the rules above; the organizers, the jury and any other relevant authority reserve the right to evaluate each case independently.
- Any action with the effect of intentionally making a service unavailable or non-functioning when interacted with by players or the checkers is prohibited.
- The deployment of fake flags is prohibited.
Please be aware that the entire game network traffic is logged, and will be accessed in case of a suspected rule violation.
Cheatsheet
A quick-reference for the most important information during the CTF.
| Key | Value |
|---|---|
| Platform | https://platform.ad.ecsc2025.pl |
| Public Scoreboard | https://scoreboard.ad.ecsc2025.pl |
| Internal Scoreboard | http://10.42.251.2 |
| Attack API | http://10.42.251.2:8080 |
| Game Network | 10.42.0.0/16 |
| Team Network | 10.42.X.0/24 |
| Team Cloud Network | 10.43.X.0/24 |
| Vulnbox IP | 10.42.X.2 (game network), 10.43.X.2 (team cloud network) |
| Gateway IP | 10.42.X.254 (game network), 10.43.X.254 (team cloud network) |
| Flag submission | nc 10.42.251.2 1337 |
Contact
Responsible Disclosure
Please send information about vulnerabilities you find in the platform directly to the organizers via the following address: ecsc2025+bugs@attacking-lab.com
If possible, encrypt your message with the key corresponding to the following fingerprint:1B83 6E52 A23C 80B1 28CB 53BF 69BD EDEF 0AEC 0D6C
Bug Bounty
We want to reward players that find and report bugs in our platform.
If you report a bug before the competition and help us triage, we will do our best to reward that show of sportsmanship. Prizes TBD.
Support
For support during the CTF, please open a ticket via the ticket bot in the ECSC 2025 Discord server.
In the unlikely case that Discord is unavailable, please send an email to the following address: ecsc2025+support@attacking-lab.com