Security¶
Rate limits on flag submissions and logins, the idle timeout for browser sessions, and the captcha on the login and registration forms.
The settings live under Admin → Settings → Security.
| Setting | Key | Default |
|---|---|---|
| Submit rate limit | rate_limit.submit.enabled |
On |
| Max submissions | rate_limit.submit.max_requests |
20 |
| Window (seconds) | rate_limit.submit.window_seconds |
60 |
| Login rate limit | rate_limit.login.enabled |
On |
| Max login attempts | rate_limit.login.max_requests |
10 |
| Window (seconds) | rate_limit.login.window_seconds |
60 |
| Idle session timeout (minutes) | auth.session_idle_minutes |
0, disabled |
| Enable captcha | captcha.enabled |
Off |
Everything but the submission limit protects sign-in, so saving it from the browser
needs a recent sign-in. Each save is recorded
in the event log as config.updated.
Rate limits¶
Both limits are sliding windows: at most Max requests in any span of Window seconds, not per calendar minute. Every attempt counts, whatever its outcome, refused ones included, and a request over the limit is refused with 429. A client that keeps retrying keeps itself locked out; one that waits a full window gets its budget back.
| Limit | Counted per | Covers |
|---|---|---|
| Submissions | Team | Every answer submitted, correct or not. |
| Logins | Client IP address | The login form, and re-authentication. |
The submission limit is shared by the whole team, whether its members submit from the browser or from scripts with API tokens, so one member's script can use up the budget for everyone. The default of 20 a minute is generous for people typing flags and tight for brute force.
The login limit trusts your proxy count
The login limit is keyed on the client address, which comes from
TRUSTED_PROXY_COUNT. Set too low, every
login appears to come from your proxy and one player's typos lock everyone out. Set
too high, a client can claim any address and slip past the limit.
Registration, password-reset requests and verification resends have fixed per-address limits of their own, which are not settings; see Authentication.
Idle session timeout¶
Signs a browser session out after that many minutes without a request, on top of the 24
hour limit every session has. 0 disables it, and the maximum is 1440, a full day.
API tokens are not affected. A short timeout suits an instance used on shared machines,
such as a classroom, where a session left open would otherwise stay signed in for the
rest of the day.
See Sessions.
Captcha¶
Enable captcha puts a proof-of-work challenge on the login and registration forms.
It is ALTCHA, self-hosted: the browser solves a small puzzle
signed with the instance's SECRET_KEY, with no third-party service to sign up for and
no request leaving your instance. Players see nothing of it: the puzzle is solved in the
background as the page loads, and the submit button waits for it, usually a fraction of
a second.
Each solution is valid for five minutes and works once, so a solved puzzle cannot be
replayed against the form. A script hitting the endpoints directly has to solve a fresh
one for every attempt, which puts a computing cost on credential stuffing and mass
registration without making a human wait. It slows a script down rather than stopping
it, so keep the login rate limit on alongside it. Failed and missing solutions are counted in the
metrics as nexctf_captcha_failures_total, by reason.
API tokens are not challenged
The captcha guards the two forms that create a session. Requests made with an API token never go through them.