cybersecurity · beginner · ~15 min · safe pentest lab
Practice deny-by-default input validation: enforce an exact length and a strict character allowlist on an attacker-controlled string, bounds-checking each byte before use, so malformed CSRF tokens are rejected before they reach trusted logic.
A CSRF (Cross-Site Request Forgery) defense hands each session a random anti-CSRF token, and the server must reject any request whose token is malformed before it is ever compared against the session secret or used to key any lookup. If a handler blindly trusts attacker-controlled token strings, an attacker can smuggle in oversized, empty, or injection-shaped values that slip past sloppy checks.
In this lab the asset is the fixed set of candidate token strings baked into the test harness. The insecure assumption you are fixing is "any non-empty string is a token": that lets "", a 33-character overflow, uppercase, whitespace, or <script> payloads through the gate.
Implement valid_csrf_format(const char *tok) so it returns 1 iff tok is exactly 32 characters long and every character is lowercase hex (0-9 or a-f), and 0 otherwise. NULL must return 0. Deny by default and never read past the token: stop at the first '\0'.
NULL input.g-z, spaces, and injection payloads.A single argument tok: a NUL-terminated C string, or NULL.
Return int 1 if tok is exactly 32 lowercase-hex characters, otherwise 0.
Do not read past the terminating NUL. Treat NULL as invalid (return 0). Only characters 0-9 and a-f are accepted; length must be exactly 32. No allocation, no I/O.
int valid_csrf_format(const char *tok){
/* TODO: validate that tok is exactly 32 lowercase-hex chars.
Insecure stub: trusts any non-NULL token. Replace me. */
(void)tok;
return 1;
}
Using strlen without a NULL check (crashes on NULL). Accepting length >= 32 instead of exactly 32, so a 40-char token passes. Forgetting to verify the 33rd byte is the terminator, so any long string with a valid 32-char prefix is accepted. Allowing uppercase hex via isxdigit() when the spec demands lowercase. Returning early with 1 before scanning all characters.
NULL pointer returns 0. Empty string returns 0. A 31-char token returns 0 (too short) and a 33-char token returns 0 (too long) — length must be exact, not "at least 32". Uppercase A-F is rejected because the spec requires lowercase. Any non-hex byte (g-z, punctuation, space, control chars) rejects the whole token. All-zero and all-f 32-char tokens are valid boundary accepts.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.