cybersecurity · intermediate · ~15 min · safe pentest lab
Validate the full structure of attacker-controlled fixed-format input character-by-character before consuming it, rejecting anything that does not match exactly instead of assuming well-formed data.
A tool ingests MAC addresses from untrusted sources (ARP tables, config files, packet fields) and copies them into a fixed 6-byte buffer used for filtering and lookups. The insecure assumption is that any string handed in is a well-formed aa:bb:cc:dd:ee:ff. If you trust that, a malformed input like a single-digit group, a wrong separator, or a truncated string lets you read past the string or write bytes you never validated, corrupting the ARP/filter table.
Your job is to parse defensively: accept ONLY the exact shape (6 groups of exactly two hex digits, lowercase or uppercase, separated by exactly five colons, then a terminating NUL) and write the 6 bytes into out. Anything else is rejected with -1 and out is not trusted. Deny by default; validate every character position BEFORE using it. The buffer is baked into the harness — this never touches a live host or network.
Given out of length 6: parse_mac("00:00:00:00:00:00", out) -> 0 and parse_mac("aa-bb-cc-dd-ee-ff", out) -> -1.
A NUL-terminated C string s (attacker-controlled) and a caller-provided 6-byte array out.
Returns int: 0 on success (out[0..5] filled), -1 if the string is malformed in any way.
A valid MAC is exactly 17 characters: 6 two-hex-digit groups joined by 5 colons. Hex digits may be 0-9, a-f, or A-F. No leading/trailing whitespace, no other separators, no shorter/longer groups. Do not read or write out of bounds for any input, including NULL.
int parse_mac(const char *s, unsigned char out[6]){
/* TODO: parse the MAC address into out[0..5].
Reject any malformed input with -1. This stub does neither. */
(void)s; (void)out;
return 0;
}
Using sscanf("%x:%x:...") which accepts single-digit groups, wrong widths, and trailing garbage; not checking that exactly 5 colons and a NUL appear at the right positions; reading s[i] before confirming the string is long enough; forgetting to reject when extra characters follow the 6th group; not handling NULL.
Empty string; NULL pointer; too few groups (truncated); too many groups (extra trailing group); single-digit group like a:b:c:d:e:f; wrong separator such as dashes; non-hex characters like g or z; trailing junk after an otherwise-valid MAC; all-zero and all-FF boundary values.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.