cybersecurity · beginner · ~15 min · safe pentest lab
Practice deny-by-default input validation: match untrusted input against a fixed allow/deny list using a safe, whole-string, bounds-respecting comparison instead of a naive prefix or substring check.
A configuration validator protects an asset: the crypto choices your service is allowed to use. The threat is a developer (or an attacker who can edit config) selecting a broken primitive like MD5, SHA-1, DES, or RC4, silently weakening TLS, password hashing, or token signing. Your job is a deny-by-default allow/deny check: given an algorithm name, decide whether it is a known-weak/broken primitive.
Implement:
int is_weak_algorithm(const char *name);
Return 1 if name matches — case-insensitively — one of the fixed weak primitives md5, sha1, des, 3des, rc4, ecb, md4; otherwise return 0. The comparison must be against the whole string: "sha256" is strong even though it starts with "sha", and "md5sum" is not "md5".
The insecure assumption to avoid is trusting attacker-controlled input length or matching only a prefix. Never read past the terminating NUL, and treat NULL as not-weak (0).
NULL input must return 0 (never dereference it).0."MD5", "Rc4") still matches.registry entry "md5sum") is not a match.Given a fixed registry array baked into the harness:
is_weak_algorithm(registry[0]) // "MD5" -> 1
is_weak_algorithm(registry[1]) // "AES" -> 0
is_weak_algorithm(registry[4]) // "sha256" -> 0
A single argument: a NUL-terminated C string name (an algorithm identifier), or NULL. The string is fully attacker-controlled in content and length.
Return int 1 if name is a known-weak primitive (case-insensitive, whole-string match), otherwise 0. NULL returns 0.
C11, freestanding-style function body. Do not allocate. Do not read beyond the terminating NUL of name. Comparison is ASCII case-insensitive over the whole string. The weak set is fixed: md5, sha1, des, 3des, rc4, ecb, md4.
int is_weak_algorithm(const char *name)
{
/* TODO: compare name (case-insensitively, whole string) against the
weak-primitive list: md5, sha1, des, 3des, rc4, ecb, md4.
Remember: NULL => 0, and a prefix like "sha" of "sha256" is NOT a match. */
(void)name;
return -1;
}
Dereferencing NULL before the guard; using strncmp/prefix matching so sha256 wrongly flags as sha1; case-sensitive comparison that misses MD5; using strstr so md5sum matches md5; forgetting one list entry (md4 or ecb); reading past the NUL when lengths differ.
NULL pointer -> 0; empty string -> 0; uppercase/mixed case matches (MD5, Rc4); a weak token that is only a prefix or substring of a longer name (sha256, md5sum, des3) must NOT match; exact matches for every listed primitive including the digit-prefixed 3des.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.