cybersecurity · intermediate · ~15 min · safe pentest lab
Practice turning a security policy into safe, bounds-checked C: validate the pointer before use, compute length by scanning to the NUL terminator, classify characters without reading out of range, and enforce an exact-match denylist rather than a loose prefix check.
You are hardening an account-creation flow. The asset is the user's account; the threat is an attacker who guesses or brute-forces weak passwords. The insecure assumption teams keep making is "any non-empty password is fine" — that lets in password, 123456, and 6-character lowercase strings that fall in seconds.
Your job is to build a strength meter, not a cracker. It never touches a network, filesystem, or live account — it scores one C string that lives in a fixed buffer inside the grading harness. Implement:
int password_strength(const char *pw);
Return a score from 0 to 4, adding one point for each rule that passes:
password, 123456, qwerty, letmeinDeny by default: a NULL pointer scores 0 and must never be dereferenced. Every scan must stop at the terminating '\0' so you never read past the buffer.
Given the identifier strong pointing at a 12-character password that mixes four classes and is not banned:
password_strength(strong) -> 4
password_strength(NULL) -> 0
A single argument: pw, a pointer to a NUL-terminated C string, or NULL. The string lives in a fixed buffer owned by the harness.
An int in the range 0..4 — the number of strength rules the password satisfies.
No dynamic allocation, no I/O, no global state. Must be memory-safe: NULL yields 0 with no dereference, and every character scan stops at the terminating '\0'. Banned-word checks must be exact full-string matches, not prefixes.
int password_strength(const char *pw){
/* TODO: implement the defensive strength score (0..4).
This insecure stub always claims maximum strength and
never bounds-checks or rejects NULL/banned input. */
(void)pw;
return 4;
}
Dereferencing pw before the NULL check. Using strlen or strcmp on a NULL pointer. Treating a banned prefix as banned (matching "password" inside "password123"). Counting length with a signed int that could overflow, or reading past the '\0'. Requiring all 4 classes when the rule only needs 3. Off-by-one on the >=8 and >=12 boundaries.
NULL pointer must return 0 without dereferencing. Empty string has length 0 and no classes but is not banned, so it scores 1. A password that merely starts with a banned word (e.g. "passwordX") is NOT banned — only exact full-string matches count. Boundary lengths 8 and 12 must each award their point. A symbol is anything outside the lower/upper/digit ranges.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.